在vue中,对于兄弟组件或者隔代组件我们通常使用Vuex实现组件通信,除此之外还可以使用Event Bus 来实现。Event Bus本质上是发布-订阅模式,在开发中应用广泛。
在vue中使用Event Bus
注册Event Bus
// main.js
// 本质上EventBus是一个vue实例 一个没有DOM的组件
Vue.prototype.$bus = new Vue()
订阅(接收)事件
// 这里func指someEvent这个事件的监听函数
this.bus.$on('someEvent', func)
发布(触发)事件
// 这里params指someEvent这个事件被触发时回调函数接收的入参
this.bus.$emit('someEvent', params)
自定义实现Event Bus
根据Event Bus的使用方法,我们手动实现一个EventBus,具体分析见注释解析
class EventBus {
constructor() {
//dep 是一个map ,用于存储事件及其回调的对应关系
this.dep = {}
}
//on 用于注册事件,接收事件名称及其回调
on(eventName, cb) {
//先检查一下目标事件是否存在
if (!this.dep[eventName]) {
//不存在,初始化一个监听函数队列
this.dep[eventName] = []
}
this.dep[eventName].push(cb)
}
//emit 用于触发目标事件,接收事件名称和函数入参
emit(eventName, ...args) {
if (this.dep[eventName]) {
// 如果存在 循环调用回调函数
this.dep[eventName].forEach((cb) => {
cb(...args)
})
}
}
//移除事件
off(eventName) {
if (this.dep[eventName]) {
delete this.dep[eventName]
}
}
//移除事件内指定回调函数
offCb(eventName, cb) {
const cbs = this.dep[eventName];
const index = cbs.indexOf(cb)
if (index !== -1) {
cbs.splice(index, 1)
}
}
//注册单次监听器(即执行完回调函数,自动销毁)
once(eventName, cb) {
const cbWrap = (...args) => {
cb(...args)
this.offCb(eventName, cbWrap)
}
//用cbWrap将事件进行包裹,使其执行完毕后,自动销毁
this.on(eventName, cbWrap)
}
}