最近两天在面试中被提及到vue组件通信的几种方式,这些都是巴拉巴拉的一堆网上可以百度到的通信方式,比如父子组件间的props和$emit,以及$refs,$children,$parent, 依赖注入,vuex,以及bus事件总线机制,因为提到了这个bus,所以面试官就问你知道bus的实现原理吗?在我之前的想法中我认为就是通信方式除了vuex需要去掌握一下原理外,其他的都是知道怎么用就好了,但是当面试官突然这么一问之后,我也突然一蒙蔽了,毕竟自己确实不知道。
基于上述原因,我现在慢慢的觉得程序的东西不仅仅需要知道怎么用,当然第一步是需要知道怎么使用,接下来就是要知道如何去实现这个技术或者插件,之前挺喜欢一位老师说的名句就是“了解真相才能获得真正的自由”
正文开始:vueBus是中央数据总线,是为了解决非关系组件间的通信问题,主要是使用了vue中的$on和$emit方法,使用发布者订阅者模式,必须在相同的实例才可以进行数据响应,中央数据总线可以使用空的vue实例来实现,有一个cache对象,使用$on新增订阅方法,通过$off进行订阅方法的删除,通过$emit实现通知订阅信息的更新。
其实bus等同于以下写法:创建一个Bus函数,创建两个方法和一个存储对象,通过$on收集依赖,通过$emit触发依赖方法。
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()
// child1
this.$bus.$on('foo', handle)
// child2
this.$bus.$emit('foo')
vueBus注意事项:
-
$bus.on应该在created钩子内使用,如果在mounted使用,它可能接收不到其他组件来自created钩子内发出的事件,
-
使用了$bus.on在beforeDestory钩子里应该需要使用$bus.off解除
顺带记得关注公众号一波分享你需要的资源