Vue dispatch、broaddcast、event-bus实现

Vue dispatch、broaddcast、event-bus实现

为什么要实现dispatch、broadcast和event-bus?

在使用Vue的过程中,我们经常会遇到组件之间的通信。父、子组件通信我们可以使用props和event实现,但是如果组件层级跨度较大或者是兄弟组件之间通信时,如果我们还是使用props和event一层一层传递的话,就会造成代码难以维护、难以阅读以及更容易出错的问题。那么我们有更好的解决方案吗?当然有,那就是dispatch、broadcast与event-bus。

dispatch、broadcast、event-bus各自的使用场景是什么?

先来说说dispatch和broadcast吧。

image.png
dispatch的作用是将事件向上传递。比如说如果一个组件触发事件的话,该事件会一层层向上传递到所有的父组件。broadcast正好和dispatch想法,broadcast的作用是向下面所有的子组件广播事件。如果实现了dispatch和broadcast,那么我们便不用props和events一层一层的通信了。

image.png

event-bus称为事件总线,其作用是在两个毫无关联的组件之间传递数据。event-bus就像一个事件的共享池,所有的组件都可以在event-bus上面订阅和发布事件,这样就实现了两个毫无管理的组件数据传递,其核心思想就是“订阅-发布”模式。

如何实现dispatch、broadcast和event-bus?

dispatch的目的是要向所有的父组件传递事件,那么我们可以通过递归所有的父组件来实现,这里我们借助$parent获取父组件实例。

1
2
3
4
5
6
7
8
9
10
11
dispatch(event,data) {
let parent = this.$parent;
while(parent) {
if(parent) {
this.$emit(event,data);
parent = parent.$parent;
} else {
break;
}
}
Vue.prototype.$dispatch = dispatch;

broadcast的作用是向下级组件广播事件,我们借助$children获取下级组件。

1
2
3
4
5
6
7
8
9
10
function broadcast(event,data) {
let children = this.$children;
children.forEach(child=>{
child.$emit(event,data);
if(child.$children.length) {
broadcast.call(child,event,data);
}
})
}
Vue.prototype.$broadcast = boardcast;

event-bus的实现是借助于“订阅-发布”模式,而Vue的实例正好实现了这一模式,所以我们只需要创建另一个Vue实例就可以实现event-bus了。

1
2
3
4
5
6
7
8
9
Vue.prototype.$bus = new Vue();

//订阅
...
this.$bus.$on(eventname,(data)=>{
...
})
//发布
this.$bus.$emit(eventname,data);

最后要说的

Vue组件之间通信出了以上列举的方法还可以使用Vuex。Vuex是官方提供的一个通用状态管理器。在中大型项目中,如果在组件间任意传递数据会导致应用的数据混乱并且难以管理,而Vuex提供了单向数据流绑定,应用中的每一个状态都可以存储到Vuex中进行统一管理。