发布订阅设计模式可以理解为制作一张计划表和执行计划
比如:张三要结婚了
计划表:把结婚当天要做的事情一件件都列举出来
结婚时:按照计划表中的计划一件件的去执行即可
发布订阅(按照了DOM2事件池的机制)
1.创建事件池
2.向事件池中追加方法/移除方法
3.通知事件池中的方法执行
事件池的机制有两种,一个是以数组为事件池,往数组里添加对象,每个对象里有事件名称与事件方法
[{ everyType:'marry', func:fn1},,,]
第二种以Object为事件池,以事件名称为键,方法组成的数组为值
{
"marry":[fn1,fn2],
"baby":[],
...
}
下面我们来实现一下这个发布订阅的流程
(function () {
const hasOwn = Object.prototype.hasOwnProperty;
class Sub {
// 创建事件池
pond = {};
// SUB.PROTOTYPE
//添加/订阅
on(type, func) {
let pond = this.pond,
listeners;
!hasOwn.call(pond, type) ? pond[type] = [] : null;
listeners = pond[type];
!listeners.includes(func) ? listeners.push(func) : null;
}
//移除
off(type, func) {
let pond = this.pond,
listeners = pond[type] || [];
if (listeners.length === 0) return;
for (let i = 0; i < listeners.length; i++) {
if (listeners[i] === func) {
// listeners.splice(i, 1); //=>会导致数组塌陷
listeners[i] = null;
return;
}
}
}
//执行/发布
fire(type, ...params) {
let pond = this.pond,
listeners = pond[type] || [];
if (listeners.length === 0) return;
for (let i = 0; i < listeners.length; i++) {
let itemFunc = listeners[i];
if (typeof itemFunc !== "function") {
listeners.splice(i, 1);
i--;
continue;
}
itemFunc(...params);
}
}
}
window.subscribe = function subscribe() {
return new Sub();
};
})();