首先,我们在什么情况下,使用到 发布订阅呢?
比如说,在React 中,我们的两个 组件,已经嵌套 很深了,我们在用 props,向下 一直传递值的话,中途的组件 就会被 污染, 增加代码量,以后的维护成本 也很高.(当然 也有其他的解决方法, react context, redux, 但是 本文只想用发布 订阅 来解决, 顺便的熟悉一下用法)
相信,大家 基本上都用过 target.addEventListener(“click”, func, false), 这个监听方法, 当我们 点击的时候 就像于一个发布, 而addEventListener,则是监听到进行对应的操作.
代码 如下:
class EventEmitter {
constructor() {
// 用来存放 订阅 和 发布的关系的
this.eventMap = {};
}
// type 这里就代表事件的名称
on(type, handler) {
// 判断 handler 的实例 是不是一个函数
if (!(handler instanceof Function)) {
throw new Error("请传入一个函数");
}
// 判断 我们的map 中是否有这个类型
if (!this.eventMap[type]) {
// 若不存在,新建该队列
this.eventMap[type] = [];
}
// 若存在,直接往队列里推入 handler
this.eventMap[type].push(handler);
}
//向上派发 消息出去
emit(type, params) {
// 假设该事件是有订阅的(对应的事件队列存在)
if (this.eventMap[type]) {
// 将事件队列里的 handler 依次执行出队
this.eventMap[type].forEach((handler, index) => {
// 这里携带参数, 触发on方法的handler 回调
handler(params);
});
}
}
// 用来 卸载掉 不用监听的方法
off(type, handler) {
if (this.eventMap[type]) {
this.eventMap[type].splice(this.eventMap[type].findIndex(handler), 1);
}
}
}
在上面的角色中,
订阅:
on(): 负责 测试 事件的监听器,指定 事件触发的回调函数, 把对应的事件和函数,写入到 eventMap 里面去
发布:
emit(): 负责触发事件,把事件发布,然后把参数携带,派发给on里面的handler的回调函数里面去
off(): 负责监听器的删除
用法
const event = new EventEmitter();
// 编写一个简单的 handler
const testHandler = function (params) {
console.log(`aaa被触发了,参数值是${params}`);
};
// 监听 aaa 事件
event.on("aaa", testHandler);
// 在触发 aaa 事件的同时,传入希望 testHandler 感知的参数
event.emit("aaa", "bbb");