发布订阅模式:
关键内容:off,on,emit,once四个方法
代码实现:
class EventEmitter {
constructor() {
this._events = {};
}
//注册事件
on(eventName, cb) {
const cbs = this._events[eventName] || []; //若本身注册过,则取之前的值,否则置为空数组
cbs.push(cb);
this._events[eventName] = cbs;
}
//发布订阅,并调度执行
emit(eventName, ...args) {
const cbs = this._events[eventName] || [];
//将调度中心同名注册下的所有事件都执行一遍
cbs.forEach((cb) => cb(...args));
}
off(eventName, cb) {
const cbs = this._events[eventName] || [];
//第二个并级判断,是为了配合once的特殊注册
this._events[eventName] = cbs.filter(
(filtItem) => filtItem !== cb && filtItem.cb !== cb
);
}
//思想:在执行一次过后就将对应函数off掉
once(eventName, cb) {
const one = (...args) => {
cb(...args);
this.off(eventName, one);
};
//此处非常重要,若不添加,则在once注册之后,emit之前就off则无法删除对应注册回调
one.cb = cb;
this.on(eventName, one);
}
}
const events = new EventEmitter();
function handleName(name) {
console.log("name1", name);
}
function handleName2(name) {
console.log("name2", name);
}
events.on("hello", handleName);
events.once("hello", handleName2);
//此时once注册的时候存储的回调函数跟实际传递的回调函数是不相等的,在没有emit之前就直接off,是没有办法删除的
events.off("hello", handleName2);
events.emit("hello", "小明");
events.emit("hello", "小王");
注意:
若one.cb=cb这句话不添加,则结果是:
name1:小明;name2:小明(没有off掉);name1:小王