发布订阅

310 阅读1分钟

发布订阅: 是一种编程的思想;

发布订阅 先进行订阅,把要执行的一些方法先存储到一个事件池中;当条件成立时,进行发布的操作;发布时,遍历事件池中的所有的方法,让这些方法依次执行;

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);