学习笔记,简要记录一下。
适用场景
监听事件的位置和触发事件的位置不受限,可以用于任意组件间的通信。Vue 中的 EventBus 就是一个典型应用。
实现思路
- 处理事件和监听函数的对应关系 —— 用对象(eventMap)存储事件和处理函数的映射关系
- 实现事件订阅 —— 往 eventMap 写入事件处理函数
- 实现事件发布 —— 从 eventMap 读取事件处理函数并依次执行
具体实现
class myEventEmitter {
constructor() {
this.eventMap = {}; // 存储事件和监听函数之间的关系
}
// type:事件名称; handler:事件处理函数
on(type, handler) {
// hanlder 必须是一个函数
if (!(handler instanceof Function)) {
throw new Error("hanler必须是函数");
}
// 判断 type 事件对应的队列是否存在
if (!this.eventMap[type]) {
// 若不存在,新建该队列
this.eventMap[type] = [];
}
// 若存在,直接往队列里推入 handler
this.eventMap[type].push(handler);
}
// type:事件名称; params:支持传参
emit(type, params) {
// 假设该事件是有订阅的(对应的事件队列存在)
if (this.eventMap[type]) {
// 将事件队列里的 handler 依次执行出队
this.eventMap[type].forEach((handler, index) => {
handler(params); // 别忘了读取 params
});
}
}
off(type, handler) {
if (this.eventMap[type]) {
this.eventMap[type].splice(this.eventMap[type].indexOf(handler) >>> 0, 1);
}
}
}
测试
// 实例化 myEventEmitter
const myEvent = new myEventEmitter();
// 编写一个简单的 handler
const testHandler = function (params) {
console.log(`test事件被触发了,testHandler 接收到的入参是${params}`);
};
// 监听 test 事件
myEvent.on("test", testHandler);
// 在触发 test 事件的同时,传入希望 testHandler 感知的参数
myEvent.emit("test", "newState");