zoukankan      html  css  js  c++  java
  • vue组件通信

    整理了vue中组件通信,分以下情况:(代码环境:vue2.0  vue-cli 3.0.1)

    一:父--》子通信

    1、通过props:

    //子组件
    <template>
      <div class="son">{{msg}}</div>
    </template>
    <script>
    export default {
      name: 'son',
      props:{
        msg:String
      }
     }
    </script>
    //父组件
    <template>
      <div class="parent">
        <son :msg="myName"></son>
      </div>
    </template>
    
    <script>
    import son from '../components/son'
    export default {
      name: 'parent',
      components:{
        son
      },
      data() { 
        return {
          myName:'hello world'
        }
      }
     }
    </script>

    以上就是将父组件parent中的myName传入到了子组件son中

    注意:根据官方文档,所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

    二:子--》父

    通过事件,使用$emit触发,具体看以下代码:

    //子组件
    <template>
      <div class="son" >
        <button @click="getNum">click</button>
      </div>
    </template>
    
    <script>
    export default {
      name: "son",
      data() {
        return {
          num:6666
        };
      },
      methods: {
        getNum() {
         this.$emit('getNum',this.num)
        }
      }
    };
    </script>
    //父组件
    <template>
      <div class="parent">
        <son @getNum="getNum"></son>
      </div>
    </template>
    
    <script>
    import son from '../components/son'
    export default {
      name: 'parent',
      components:{
        son
      },
      methods:{
        getNum(e){
          console.log(e)//可以获取到子组件中的num值
        }
      }
     }
    </script>

    三:其实父子组件通信还可以使用vm.$refs  一个对象,持有注册过 ref特性 的所有 DOM 元素和组件实例。

    //父组件   通过调用子组件的方法,以参数的形式传入到子组件中;同样的子组件也可以使用方法将值传到父组件中
    <template>
      <div class="parent">
        <son ref="son"></son>
      </div>
    </template>
    <script>
    import son from '../components/son'
    export default {
      name: 'parent',
      components:{
        son
      },
      data() { 
        return {
          myName:'hello world'
        }
      },
      mounted(){
        this.$refs.son.getName(this.myName)
       console.log(this.$refs.son.getNum())//输出的就是子组件中num值 } }
    </script>
    //子组件
    <template>
      <div class="son"> </div>
    </template>
    <script>
    export default {
      name: "son",
     data(){return {num:123}}, methods: { getName(e) { console.log(e)
    //e就是传入的myName值 },
      getNum(){
        return this.num
      }
    } };
    </script>

    注意:根据官方文档 $refs 只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问 $refs

    因此还是不建议使用ref来进行父子之间的数据传递;

    四:非父子组件中的数据传递

    1、路由url传递

    • 在传统开发时我们常常把需要跨页面传递的数据放到url后面,跳转到另外页面时直接获取url字符串获取想要的参数即可,在vue跨组件时一样可以这么做,

      // router index.js 动态路由
      {
         path:'/params/:Id',
         component:Params,
         name:Params
      }
      // 跳转路由
      <router-link :to="/params/12">跳转路由</router-link>
    • 在跳转后的组件中用$route.params.id去获取到这个id参数为12,但这种只适合传递比较小的数据,数字之类的

    2、 eventBus通信   

       eventBus这种通信方式,针对的是非父子组件之间的通信,它的原理还是通过事件的触发和监听。

      但是因为是非父子组件的关系,他们需要有一个中间组件来连接。

      使用eventBus传递数据,我们一共需要做3件事情

    • 1.在组件之外定义一个bus.js作为组件间通信的桥梁,适用于比较小型不需要vuex又需要兄弟组件通信的,或者给app组件添加Bus属性 (这样所有组件都可以通过this.$root.Bus访问到它,而且不需要引入任何文件)
    • 2.在组件1里,this.$root.Bus.$emit触发事件
    • 3.在组件2里,this.$root.Bus.$on监听事件
      //bus.js
      import Vue from 'vue'
      export default new Vue()
      /*
      或者在main.js中添加Bus属性
      import Vue from 'vue'
      new Vue({
        el: '#app',
        components: { App },
        template: '<App/>',
        data(){
          return {
            Bus : new Vue()
          }
        }
      })
      通过this.$root.Bus.$emit()/.$on()来处理
      */
      //组件1
      <template>
        <div class="home">
            <button  @click="handlerClick">clickBus</button>
        </div>
      </template>
      
      <script>
      // @ is an alias to /src
      import Bus from '../models/bus'
      export default {
        name: "home",
        methods:{
          handlerClick(){
      Bus.$emit(
      'handlerClick','兄弟组件传递参数')
      } } }; </script>
      //组件2
      <template>
      <div class="about">
          <h1>This is an about page</h1>
        </div>
      
      </template>
      <script>
      import Bus from '../models/bus'
      export default {
        data(){
          return {}
        },
        mounted(){
          Bus.$on('handlerClick',(e=>{
      console.log(e) })) } }; </script>

      注意:首屏渲染完之后,没有进入组件2,在组件1中直接点击handlerClick按钮时,并不会触发组件2中的clickBus事件,可能是这时候组件2并没有渲染事件并没有绑定,无法触发

    五:祖--》孙

      如果跨组件传递通过以上一步步的传递是比较麻烦的,可以使用$attr来实现祖孙之间的传递

      意思就是父组件传向子组件传的,子组件不prop接受的数据都会放在$attrs中,子组件直接用this.$attrs获取就可以了。如过从父->孙传,就在子组件中添加v-bind='$attrs',就把父组件传来的子组件没props接收的数据全部传到孙组件,具体看以下代码

    //祖组件
    <template>
      <div class="grandFather">
    <parent :number="num" :output="myName"></parent>
      </div>
    </template>
    
    <script>
    import parent from './Parent'
    export default {
      name: 'grandFather',
      components:{
        parent
      },
      data() { 
        return {
          num:666,
          myName:'grandFather'
        }
      }
     }
    </script>
    //父组件
    <template>
      <div class="parent">
        <son v-bind="$attrs" ></son>
      </div>
    </template>
    
    <script>
    import son from '../components/son'
    export default {
      name: 'parent',
      components:{
        son
      },
      props:{
        number:Number//这里在父组件中定义了number,因此在父组件以及子组件中this.$attrs无法获取number值
      },
     mounted(){
       console.log(this.$attrs)//打印output
     }
     }
    </script>
    //子组件
    <template>
      <div class="son" >
       son
      </div>
    </template>
    
    <script>
    export default {
      name: "son",
      mounted(){
        console.log(this.$attrs)//打印output
      }
    };
    </script>

    得到一下输出结果:

    六:其他的通信方式

    1、用localStorage或者sessionStorage这种通信比较简单,缺点是数据和状态比较混乱,不太容易维护。

      通过window.localStorage.getItem(key) 获取数据
      通过window.localStorage.setItem(key,value) 存储数据

      注意用JSON.parse() / JSON.stringify() 做数据格式转换。

    2、provide/inject还有$children/$parent 

    3、使用vuex

    参考文章:

    整理4种Vue组件通信方式

    vue组件通信全面总结

    以上是根据上面两篇文章进行的总结,如果看不懂可以访问原链接,原文里面也有其他的方法可以参考,有错误的地方希望可以提出。

  • 相关阅读:
    Spring Boot 的常用 API 说明
    错误:No WebApplicationContext found: no ContextLoaderListener or DispatcherServlet registered?
    [剑指offer] 2. 替换空格
    [剑指offer] 1. 二维数组中的的查找
    [leetcode] 300. Longest Increasing Subsequence (Medium)
    [leetcode] 929. Unique Email Addresses (easy)
    微信小程序post 服务端无法获得参数问题
    python虚拟环境管理 Pipenv 使用说明
    [leetcode] 87. Scramble String (Hard)
    [leetcode] 456. 132 Pattern (Medium)
  • 原文地址:https://www.cnblogs.com/hongll/p/10650381.html
Copyright © 2011-2022 走看看