Vue组件通信方式
1、props / $emit
![](https://img.haomeiwen.com/i15528678/ea250eb31242087c.png)
props是只读的,如果子组件尝试直接修改某个属性值会报错,需要将数据传递给父组件,由父组件来修改,这时可以使用$emit。
不过如果属性使用了sync修饰符:
![](https://img.haomeiwen.com/i15528678/93a0e6dc33b3564b.png)
加上sync,相当于自动为你监听了此属性的更新:
![](https://img.haomeiwen.com/i15528678/cccae57114e4207c.png)
在子组件中可以通过this.$emit('update:attrName', newValue) 的方式来修改这个属性值。
2、ref
- ref,用来给元素或子组件注册引用信息 ,引用信息会注册到父组件的$refs对象上,这个对象包含所有注册过ref的子组件 / 普通DOM元素;
- ref如果在普通的DOM 元素上使用,引用指向的就是DOM元素,就不需要我们再去用document.getElementById或者document. querySelector这种方法去获取了;
- 如果用在子组件上,引用就指向组件实例,如果子组件用于v-for中时,获取到的就是一个数组。
$refs在组件渲染完成后生效,不应在模板中使用它来做数据绑定;mounted阶段只能确保拿到那些直接写在html中的、不通过数据或者条件渲染的组件/DOM;而通过数据/条件渲染的要在vm.$nextTick()的回调中才能确保访问到。
3. $parent / $children
注意:$children并不保证顺序,是页面加载组件的顺序
4.EventBus
事件总线,创建一个vue实例作为事件管理器,在组件中触发某事件,在另一个组件中监听 。各组件的$eventBus就指向同一个vue实例,利用这个实例的$on和$emit实现通信。
![](https://img.haomeiwen.com/i15528678/ca49edae4456cdab.png)
但创建全局EventBus的问题是,所有组件都共用这个$eventBus对象,而当这两个组件销毁后,$eventsBus对象依然存在,所以在组件销毁时应该用$off移除事件监听,防止多次注册监听
5.Vuex
6.localStorage / sessionStorage
7.$attrs / $listeners 关于多层级组件之间的通信
假设组件层级为:C为B的父组件,B为A的父组件
利用$listeners,可以在C中直接监听到A派发的事件。用法是当B在使用A时给A添加一行v-on="$listeners"
![](https://img.haomeiwen.com/i15528678/5e76ac5b4c152df0.png)
先打印一下B实例上的$listeners对象:
![](https://img.haomeiwen.com/i15528678/bb498089b8fef729.png)
![](https://img.haomeiwen.com/i15528678/ba3f593d2f7c2209.png)
最后一个小注意点:用.native修饰的事件监听器不会包含在$listeners里。
$attrs的用法跟$listeners类似,在B使用A时,先给A添加一行v-bind="$attrs",A就可以接收到C(它的祖先组件)传的属性了
![](https://img.haomeiwen.com/i15528678/5984ef983ca00453.png)
![](https://img.haomeiwen.com/i15528678/07a19ced9770e37a.png)
先打印一下B实例上的$attrs对象:
![](https://img.haomeiwen.com/i15528678/3e8ec8050da62499.png)
![](https://img.haomeiwen.com/i15528678/4582c8d5bf1d86f1.png)
当我们给组件3个属性,而它只在props接收了1个,剩下的2个会渲染到这个组件的根元素上,并记录在
attrs对象)
8.provide / inject
provide / inject,它允许祖先向其后代注入一个依赖,在祖先中通过provide来提供属性,在后代中通过inject来注入变量。
节点: inject > data > provide > created
![](https://img.haomeiwen.com/i15528678/fceb8e595be9b601.png)