发布订阅: 是一种编程的思想;
发布订阅
先进行订阅,把要执行的一些方法先存储到一个事件池中;当条件成立时,进行发布的操作;发布时,遍历事件池中的所有的方法,让这些方法依次执行;
attachEvent : DOM2级兼容的处理就是采用发布订阅的思想;
发布订阅又叫自定义事件模式或观察者模式;
on:订阅事件; emit:发布事件; off:取消订阅;
let obj = {};
function fn1() {console.log("牛奶");}
function fn2() {console.log("鸡排");}
function fn3() {console.log("豆浆");}
//订阅,有三个参数:1. 订阅对象 2.订阅类型 3.订阅的方法
function on(obj,type,fn) {
if (!obj[type]) {
//第一次执行,给obj新增健值对,并且属性值是空数组;
obj[type] = [];
}
let ary = obj[type]; //取到这个数组
//遍历ary中的数组成员,判断是否绑定过;
for (let i = 0; i < ary.length; i++) {
if (ary[i] === fn) {
return;
}
}
ary.push(fn);
}
//发布:让订阅的函数依次执行;
function emit(obj,type) {
let a = obj[type];
if (a) { //如果a为undefined,不进循环
for (let i = 0; i < a.length; i++) {
if (typeof a[i]==="function") {//如果是null的话不执行
// a[i](); //this指向a,a[i]()相当于a.i();
a[i].call(obj);//改变this指向,指向obj
}
}
}
}
//取消订阅
function off(obj,type,fn) {
let ary = obj[type];
for (let i = 0; i < ary.length; i++) {
if (ary[i] === fn) {
// ary.splice(i,1);//会引起数组塌陷;
ary[i] = null; //用来占位,处理数组塌陷
return;
}
}
}
on(obj,"breakfast",fn1);
on(obj,"breakfast",fn3);
off(obj,"breakfast",fn3);
on(obj,"lunch",fn2);
setTimeout(function () {
emit(obj,"breakfast");
},2000);
setTimeout(function () {
emit(obj,"lunch");
},4000);