今天来梳理一下组件间通讯之一的事件总线,在项目中也是高频出现的一个设计模式
总的来说有两个角色,一个是消息的发布者(一个),一个是消息的接收者(多个)
知道总体的一个关系,那么我们就可以实现一个自己的EventBus
1.创建一个类并创建一个事件池
class EventBus {
private events: {
[key: string]: Array<{fn: Function, isOnce: boolean}>
}
constructor() {
this.events = {}
}
}
后续就会慢慢看懂事件池为什么数据结构这样定义
2.定义消息发布
post(eventName: string, ...args: any[]) {
const eventList = this.events[eventName]
if (!eventList) return
eventList.filter((item) => {
const {fn, isOnce} = item
fn(...args)
return !isOnce
})
}
isOnce代表的是是否只订阅一次,filter函数return假值会返回一个空数组,那么对应的eventName中的订阅者就会清空,实现once的功能
3.定义消息订阅
register(eventName: string, fn: Function, isOnce: boolean=false) {
if (!this.events[eventName]) {
this.events[eventName] = []
}
this.events[eventName].push({fn, isOnce})
}
4.定义消息只订阅一次
registerOnce(eventName: string, fn: Function) {
this.register(eventName, fn, true)
}
5.定义消息取消订阅
unregister(eventName: string, fn: Function) {
if (fn) {
// 只取消订阅某个订阅者
let eventList = this.events[eventName]
eventList = eventList.filter(item => {
return item.fn != fn
})
} else {
// 根据消息名全部取消
this.events[eventName] = []
}
}
好了,最重要的几个方法全部实现好了。主要思路就是根据一个个消息名来创建的一个无序对象,对象的value就是数组,保存订阅者的方法和isOnce。现在回过头来看
private events: {
[key: string]: Array<{fn: Function, isOnce: boolean}>
}
就比较清晰了