vue组件之间通信的6种方法

最近在面试一些前端,每当我问起父子组件,兄弟组件之间怎么传值的时候,都回答的支支吾吾,要么回答的支支吾吾,要么回答的不是很全面,在现今前端组件式开发的热潮中,这些是多么的重要,所以今天抽空整理一下,希望给他们一些帮助。

  • props 和 $emit(普遍)
  • $attrs 和 $listeners(父-子-孙)
  • provide 和 inject(父组件向下传递)
  • $parent 和 $children(父子组件数据操作)
  • eventBus (兄弟组件)
  • vuex (状态管理器)
1、props 和 $emit

父组件A向子组件B通过prop传递数据,子组件B通过$emit触发事件传递数据给父组件A

Vue.component('A',{
    template:`
      <div>
        <p>this is parent compoent!</p>
        <B :message="message" @getB="getB"></B>
      </div>
    `,
    data(){
      return {
        messageA:'hello A'
      }
    },
    methods:{
      //子组件事件
      getChild(val){
        console.log(val)
      }
    }
  })
Vue.component('B',{
    data(){
      return {
        messageB:this.messageA
      }
    },
    template:`
      <div><input type="text" v-model="messageB" @input="setData(messageB)"></div>
    `,
    props:['messageA'], //父组件传递过来的数据
    methods:{
      setData(val){
        //传递给父组件
        this.$emit('getB',val)
      }
    }
  })
2、$attrs 和 $listeners

父组件A到孙组件C传递数据的时候在用上面的方法,父A传子B,子B传孙C,这样传递虽然也能实现,但是太过于繁琐,所于就出现了$attrs 和 $listeners之间让父组件A把消息传递给孙组件C

 Vue.component('A',{
    template:`
      <div>
        <p>this is parent compoent!</p>
        <B :messageC="messageC" :messageA="messageA" @getC="getC" @getB="getB(messageA)"></B>
      </div>
    `,
    data(){
      return {
        messageA:'hello A',
        messageC:'hello C' //传递给C组件
      }
    },
    methods:{
      getB(val){
        console.log('B组件的数据')
      },
      //触发C组件的事件
      getC(val){
        console.log("C组件的数据:"+val)
      }
    }
  })
  Vue.component('B',{
    data(){
      return {
       messageB:this.messageA
      }
    },
    template:`
      <div>
        <input type="text" v-model="messageB" @input="setData(messageB)">
        <C v-bind="$attrs" v-on="$listeners"></C>
      </div>
    `,
    props:['messageA'],//父组件A传递过来的数据
    methods:{
      setData(val){
        //触发父组件A的事件
        this.$emit('getB',val)
      }
    }
  })
Vue.component('C',{
    template:`
      <div><input type="text" v-model="$attrs.messageC" @input="setCData($attrs.messageC)"></div>
    `,
    methods:{
      setCData(val){
        //触发父组件A中的事件
        this.$emit('getC',val)
      }
    }
  })
3、provide 和 inject

provide 和 inject,他们成对出现,不管子组件有多少级,用于父级组件向下传递数据。在父组件A中通过provider来设置变量,在子组件B中通过inject来引入变量。

Vue.component('A',{
    template:`
      <div>
        <p>this is parent compoent!</p>
        <B></B>
      </div>
    `,
    provide:{
      name:'my is parent compoent'
    },
    data(){
      return {
        message:'helloA'
      }
    }
  })
Vue.component('B',{
    inject:['name'],//获取父组件A传递过来的数据
    data(){
      return {
        messageB:this.name
      }
    },
    template:`
      <div>
        <input type="tet" v-model="messageB">
      </div>
  })
4、$parent 和 $children

在父子组件中可以通过$parent 和 c h i l d r e n 进 行 数 据 交 互 , 父 组 件 A 可 以 通 过 children进行数据交互,父组件A可以通过 childrenAchildren对子组件B进行操作,子组件B可以通过$parent对父组件A进行操作。

Vue.component('A',{
    template:`
      <div>
        <p>this is parent compoent!</p>
        <button @click="changeA">确定</button >
        <B></B>
      </div>
    `,
    methods:{
      changeA(){
        this.$children[0].messageB = this.messageA;//改变子组件B的值
      }
    },
    data(){
      return {
        messageA:'hello A'
      }
    }
  })
Vue.component('B',{
    data(){
      return {
        messageB:'hello B'
      }
    },
    methods:{
      changeB(){
        this.$parent.messageA = this.messageB;//改变父组件A的值
      }
    },
    template:`
      <div>
        <input type="text" v-model="messageB" @change="changeB">
      </div>
  })
  var app = new Vue({
    el:'#app',
    template:`<div><A></A></div>`
  })
5、eventBus

如果不是父子组件,是兄弟组件可以用eventBus进行操作,可以创建一个单独的js文件eventVue.js,内容如下:

import Vue from 'vue'
export default new Vue

也可以新建一个vue事件eventBus对象,然后通过eventBus. e m i t 触 发 事 件 , e v e n t B u s . emit触发事件,eventBus. emiteventBus.on监听触发的事件

var eventBus = new Vue();

第一种

Vue.component('A',{
    template:`
      <div>
        <B></B>
        <C></C>
      </div>
    `
  })
Vue.component('B',{
    import eventVue from '../../js/eventVue.js'
    data(){
      return {
        messageB:'hello B'
      }
    },
    methods:{
      submit(){
        eventVue.$emit("myFun",this.msg)   //$emit这个方法会触发一个事件
      }
    },
    template:`
      <div>
        <button @click="submit">确定</button>
      </div>`
  })
Vue.component('C',{
    import eventVue from '../../js/eventVue.js'
    data(){
      return {
        messageC:'hello C'
      }
    },
    created(){
       eventVue.$on("myFun",(message)=>{ //这里最好用箭头函数,不然this指向有问题
            this.messageC= message      
       })
    },
    template:`
      <div>
        <div>{{messageC}}</div>
      </div>`
  })
  var app = new Vue({
    el:'#app',
    template:`<div><A></A></div>`
  })

第二种

Vue.component('A',{
    data(){
      return {
        messageA:'hello A'
      }
    },
    methods:{
      submit(){
        eventVue.$emit("myFun",this.msg)   //$emit这个方法会触发一个事件
      }
    },
    template:`
      <div>
        <button @click="submit">确定</button>
      </div>`
  })
Vue.component('B',{
    data(){
      return {
        messageB:'hello B'
      }
    },
    created(){
       eventVue.$on("myFun",(message)=>{ //这里最好用箭头函数,不然this指向有问题
            this.messageB= message      
       })
    },
    template:`
      <div>
        <div>{{messageB}}</div>
      </div>`
  })
  var eventBus = new Vue();
  var app = new Vue({
    el:'#app',
    template:`<div>
    <A></A>
    <B></B>
    </div>`
  })
6、vuex

业务逻辑复杂的,组件间需要处理一些公共的数据的可以选择vuex,在这里就不多说了,相信大家学习vue的都了解vuex.

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值