Vue组件之间的通信方式总结,含父子组件通信、兄弟组件通信、跨级通信

一、什么是Vue组件通信

组件是 Vue 最强大的功能之一,Vue 中每一个 .vue 我们都可以视之为一个组件。

组件间通信,即指组件(.vue)通过某种方式来传递信息以达到某个目的。

组件通信的目的:让组件之间互相能进行通讯,这样才能构成一个有机的完整系统。

二、组件间通信的分类:

  • 父子组件之间的通信
  • 兄弟组件之间的通信
  • 祖孙与后代组件之间的通信
  • 非关系组件间之间的通信

三、Vue中8种常规的组件通信的方案

1、props传递数据

适用场景:父组件传递数据给子组件

过程:子组件设置 props 属性,定义接收父组件传递过来的参数;父组件在使用子组件标签中通过字面量来传递值。

  // Children.vue 子组件
  props: {
    // 字符串形式
    name: String, // 接收的类型参数
    // 对象形式
    age: {
      type: Number, // 接收的类型为Number类型
      default: 18, // 默认值为18
      require: true // age属性必须传递
    }
  }


  // ​​​​​​​Father.vue 父组件
  <Children name="小草莓" age=18 />  

2、$emit 触发自定义事件

适用场景:子组件传递数据给父组件

过程:子组件通过 $emit 触发自定义事件,$emit 第二个参数为传递的数值;父组件绑定监听器获取到子组件传递过来的参数

// Children.vue 子组件
this.$emit('add', good)


// Father.vue 父组件
<Children @add="cartAdd($event)" />  

​

3、ref

适用场景:获取子组件数据

过程:父组件通过设置子组件 ref 来获取子组件的数据

// Father.vue 父组件
<Children ref="foo" />  

// 获取子组件实例,通过子组件实例我们就能拿到对应的数据    
this.$refs.foo  

ref 的作用:

① 如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;

② 如果用在子组件上,引用就指向组件实例。可以通过实例直接调用组件的方法或访问数据。

 

4、中央事件总线 eventBus

适用场景:兄弟组件传值

过程:创建一个中央事件总线 EventBus,兄弟组件通过 $emit 触发自定义事件,$emit 第二个参数为传递的数值;另一个兄弟组件通过 $on 监听自定义事件

Bus.js

// 创建一个中央时间总线类  
class Bus {  
  constructor() {  
    this.callbacks = {};   // 存放事件的名字  
  }  
  $on(name, fn) {  
    this.callbacks[name] = this.callbacks[name] || [];  
    this.callbacks[name].push(fn);  
  }  
  $emit(name, args) {  
    if (this.callbacks[name]) {  
      this.callbacks[name].forEach((cb) => cb(args));  
    }  
  }  
}  
  
// main.js  
Vue.prototype.$bus = new Bus() // 将$bus挂载到vue实例的原型上  
// 另一种方式  
Vue.prototype.$bus = new Vue() // Vue已经实现了Bus的功能  

Brother1.vue 兄弟组件1

// 给注册了foo这个事件的兄弟们传递数据啦~~
this.$bus.$emit('foo', '我是参数哦')

Brother2.vue 兄弟组件2

this.$bus.$on('foo', this.handle) 

handle(e) {
  console.log('获取到兄弟组件1传递来的数据', e)
} 

5、$parent 或者 $root

适用场景:兄弟组件传值

过程:通过共同祖辈 $parent 或者 $root 搭建通信桥梁,兄弟组件通过 $emit 触发自定义事件,另一个兄弟组件通过 $on 监听自定义事件。

// 兄弟组件
this.$parent.$on('add', this.add)

// 另一个兄弟组件
this.$parent.$emit('add')

6、$attrs 和 $listeners (Vue 2.4开始提供)

背景:如果父组件A下面有子组件B,组件B下面有组件C,这时如果组件A想传递数据给组件C怎么办呢? 要实现能够让组件A之间传递消息给组件C

适用场景:祖先传递数据给子孙

过程:设置批量向下传属性 $attrs 和 $listeners,包含了父级作用域中不作为 prop 被识别 (且获取) 的特性绑定 ( class 和 style 除外)。可以通过 v-bind="$attrs" 传⼊内部组件

// child:并未在props中声明foo  
<p>{{$attrs.foo}}</p>  
  
// parent  
<HelloWorld foo="foo"/>  
// 爷爷组件页面:给Grandson隔代传值,communication/index.vue  
<Child2 msg="孙子,你好啊" @grand-son="onGrandSonEvent"></Child2>  
  
// 儿子组件页面:Child2做展开  
<Grandson v-bind="$attrs" v-on="$listeners"></Grandson>  
  
// 孙子组件:Grandson使⽤  
<div @click="$emit('grand-son', '爷爷,你好啊')">  
{{ $attrs.msg}}  
</div>  

7、provide 和 inject 

① 父组件中通过 provide 来提供变量,然后在子组件中通过 inject 来注入变量。

② 不论子组件有多深,只要调用了 inject 那么就可以注入 provide 中的数据。而不是局限于只能从当前父组件的 prop 属性来获取数据。只要在父组件的生命周期内,子组件都可以调用

适用场景:祖先传递数据给子孙

过程:在祖先组件定义 provide ​​​​​​​属性,返回传递的值​​​​​​​。在后代组件通过 ​​​​​​​inject 接收组件传递过来的值

// 祖先组件
provide() {
  return {
    foo: '这是祖传的'
  }
}

// 后代组件
// 获取到祖先组件传递过来的值
inject: ['foo']

8​​​​​​​、Vuex

Vuex ​​​​​​​作用相当于一个用来存储共享变量的容器  

适用场景:复杂关系的组件数据传递 

过程: 

  • state 用来存放共享变量的地方;

  • getter 可以增加一个 getter 派生状态,(相当于 store 中的计算属性)用来获得共享变量的值;

  • mutations 用来存放修改 state 的方法;

  • actions 也是用来存放修改state的方法,不过 action 是在 mutations 的基础上进行。常用来做一些异步操作。

四、总结

1、父子组件通信

① 常用:props / $emit 

① 父组件向子组件传递数据是通过 prop 传递的;
② 子组件传递数据给父组件是通过 $emit 触发事件来做到的;

② 其它

ref 、provide / inject  依赖注入、$parent、$attrs / $listeners

 

2、兄弟组件通信

① 常用:eventBus 

如果两个组件不是父子关系呢?这种情况下可以使用中央事件总线的方式

新建一个 Vue 事件 bus 对象,然后通过 bus.$emit 触发事件,bus.$on 监听触发的事件。

② 其它

$parent、Vuex

 

3、祖先与后代组件

① 常用:provide 和 inject 
② 其它

 $attrs 和 $listeners

 

4、跨级通信 / 复杂关系的组件

① 常用:Vuex

复杂关系的组件数据传递可以通过vuex存放共享的变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值