事件总线是实现基于事件驱动模式的方式之一,事件发送者将事件消息发送到一个事件总线上,事件订阅者向事件总线订阅和接收事件,然后再处理接收到的事件。当然,订阅者不仅可以接收和消费事件,它们本身也可以创建事件,并将它们发送到事件总线上。
事件总线是对发布-订阅模式的一种实现。它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种解耦的目的。
我们如果想要实现一个自定义的EventBus,那么首先就需要明白需要实现什么功能:
class EventBus {
constructor() {
this.events = {}; // 初始值为空对象
}
//订阅事件
on(eventKey, fn, isOnce = false) {
const events = this.events; // 引用赋值
if (events[eventKey] == null) {
events[eventKey] = []; // 初始化eventKey对应的fn数组
}
// 将函数添加到数组中
events[eventKey].push({fn,isOnce});
}
//订阅事件,只会执行一次
once(eventKey, fn) {
// 代码复用
this.on(eventKey, fn, true);
}
//取消订阅
off(eventKey, fn) {
// 如果传入了函数,但是未指定eveneky,直接不执行
if (!eventKey && fn) return;
if (!eventKey && !fn) {
// 如果未传入参数,则清除所有绑定的函数
this.events = {};
} else if (eventKey && !fn) {
// 解绑当前eventKey对应的函数
this.events[eventKey] = [];
} else {
// 解绑eventKey和fn对应的函数
if (this.events[eventKey]) {
this.events[eventKey] = this.events[eventKey].filter(item => item.fn !== fn);
}
}
}
//发布事件
emit(eventKey, ...args) {
const fnList = this.events[eventKey]; // 引用赋值
if (fnList == null) return;
this.events[eventKey] = fnList.filter(item => {
const {fn,isOnce} = item;
fn(...args); // 执行函数,并传入额外参数
if (!isOnce) return true; // 如果不是once,表示后续还可以继续被执行
return false; // 如果是once,表示执行一次后就要被过滤掉
})
}
}