发布订阅系统
class EventCenter {
eventList = new Map(); // 1
// 绑定
on(name, fn) {
let eventInfo = this.eventList.get(name);
if (!eventInfo) { // 2
eventInfo = {
data: {},
callback: new Set(),
};
this.eventList.set(name, eventInfo); // 3
}
eventInfo.callback.add(fn); // 4
}
// 解除绑定
off(name, fn) {
let eventInfo = this.eventList.get(name);
if (eventInfo && typeof fn === "function") { // 5
eventInfo.callback.delete(name);
}
}
// 只执行一次的订阅事件
once(name,fn) {
let newFn = (...args) => {
fn(...args);
this.off(name, newFn);
};
this.on(name, newFn);
}
// 发送数据
dispatch(name, data) {
let eventInfo = this.eventList.get(name);
if (eventInfo && eventInfo.data !== data) { // 6
eventInfo.data = data;
for (const f of eventInfo.callback) { // 7
f(data);
}
}
}
}
// 测试数据
const eventCenter = new EventCenter();
let fn = (data) => {
console.log(data);
};
eventCenter.on("test", fn);
eventCenter.dispatch("test", "测试数据1"); // 打印:测试数据1
eventCenter.dispatch("test", "测试数据1"); // 和前一次的数据相同不会触发事件
eventCenter.dispatch("test", "测试数据3"); // 打印:测试数据3
eventCenter.off("test", fn);
eventCenter.dispatch("test", "测试数据4"); // 已经解除监听,不会打印
eventCenter.once("once", fn);
eventCenter.dispatch("once", "测试只会触发一次1"); // 打印:测试只会触发一次1
eventCenter.dispatch("once", "测试只会触发一次2"); // 已经触发过一次,这里不会再次打印
详细过程描述
- 缓存数据和绑定函数
- 如果没有缓存则初始化
- 放入缓存中
- 记录绑定函数
- eventInfo存在且fn为函数则卸载指定函数
- 当数据不相等时才更新
- 遍历执行所有绑定函数