Vue组件之间的通信方式有哪些?
组件间通信的概念
我们把组件间通信进行拆分:
组件
通信
组件是vue
最强大的功能之一,vue
中每一个.vue
我们都可以视为一个组件。
通信指的是发送者通过某种媒体以某种格式来传递信息到收信者以达到某个目的。
组件间通信即指组件(.vue
)通过某种方式来传递信息以达到某个目的。
举个例子,我们在使用UI
库中的List
组件,会往List
组件中传递某个信息,这本质上就形成了组件之间的通信
组件间通信解决了什么
通信的本质是信息同步。
vue
中,每个组件之间都有独自的作用域,组件间的数据是无法共享的,但实际开发工作中我们常常需要让组件之间共享数据,这也是
组件通信的目的,让它们相互之间能进行通信,这也才能构成一个有机的完整系统
组件间通信的方案
props传递数据
- 适用场景:父组件传递数据给子组件
- 子组件设置
props
属性,接收父组件传递过来的参数
Children.vue
组件
vue
props: {
item: {
type: Object,
default() {
return {}
}
}
}
Father.vue
组件
vue
<Children :item="{}"/>
$emit触发自定义事件
- 适用场景:子组件传递数据给父组件
- 子组件通过
$emit
触发自定义事件,$emit
第一个参数是父组件接收的方法名,第二个参数
Children.vue
vue
this.$emit('add', good)
Father.vue
vue
<Children @add="cartAdd" />
ref
- 父组件在使用子组件的时候设置
ref
- 父组件通过子组件的
ref
来获取数据
Father.vue
vue
<Children ref="childrenRef"/>
this.$refs.childrenRef // 获取子组件实例,通过这个实例可以获取子组件的数据、方法
EventBus
- 使用场景:兄弟组件传值
- 创建一个中央事件总线
EventBus
- 兄弟组件通过
$emit
触发自定义事件,$emit
第二个参数为传递的值 - 另一个兄弟组件通过
$on
监听自定义事件
Bus.js
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的功能
Children1.vue
vue
this.$bus.$emit('foo')
Children2.vue
vue
this.$bus.$on('foo', this.handle)
parent、root
- 通过共同祖辈
$parent
或者$root
搭建通信桥梁
兄弟组件
vue
this.$parent.on('add', this.add)
另一个兄弟组件
vue
this.$parent.emit('add')
attrs与listeners
- 适用场景:祖先传递数据给子孙
- 设置批量向下传属性
$attrs
和$listeners
- 包含了父级作用域中不作为prop被识别(且获取)的特性绑定(class和style除外)
- 可以通过
v-bind="$attrs"
传入内部
vue
// child:并未在props中申明foo
<p>{{$attrs.foo}}</p>
// parent
<HelloWorld foo="foo"/>
vue
// 给Grandson隔代传值,communication/index.vue
<Child2 msg="lalala" @some-event="onSomeEvent"></Child2>
// Child2做展开
<Grandson v-bind="$attrs" v-on="$listeners"></Grandson>
// Grandson使用
<div @click="$emit('some-event', 'msg from grandson')">
{{msg}}
</div>
provide与inject
- 在祖先组件定义
provide
属性,返回传递的值 - 在后代组件通过
inject
接收组件传递过来的值
祖先组件
vue
provide(){
return {
foo:'foo'
}
}
后代组件
vue
inject:['foo'] // 获取到祖先组件传递过来的值
vuex或pinia
- 适用场景:复杂关系的组件数据传递
总结
我项目里父子组件数据通信用props和emit,除此以外组件数据通信用vuex或pinia。