发布订阅模式

DOM0 和DOM2 事件 & 发布订阅模式

1.语法上的区别

	//DOM0
	box.onclick = function(){}
	window.onload = function(){}
	
	//DOM2
	box.addEventListener('click',function(){})
	
	$(document).ready() =>$(function(){})

2.底层运行机制上的区别

	//DOM0 就是给元素的某个属性绑定方法 (有效绑定方法只有一个)
	box.onclick = function(){}
	
	//DOM2 是基于事件池机制完成的,每增加一个绑定的方法,都会往事件池中存放一个,事件触发会依次执行事件池中	   的事件 =>(发布订阅模式其实就是模拟的事件池机制,可以给同一个元素的某个事件绑定多个不同的方法)
	box.addEventListener('click',function(){})

3.DOM2中可以给一些特殊的事件类型绑定方法

DOMContentLoaded DOM结构加载完成触发

transitionend CSS3 Transition 动画完成

4. DOM2的事件池机制

  1. 基于addEventListener/attachEvent(IE6-8) 向事件池中追加方法:新版本浏览器会根据元术个事件类型对新增的方法做重复效验,但是IE6~8不可以

    
    //触发的事件
    function clickMe(){
    	console.log('11111')
    }
    var btn = document.querySelector('.btn');
    btn.addEventListener('click',clickMe);
    btn.addEventListener('click',clickMe);
    //console.log 只会输入一个 11111
    
  2. 当事件行为触发,会把事件池中的方法按照增加的顺序依次执行,但是IE6~8中的执行顺序不固定

5. JQ中的发布订阅

$.Callbakcs() add / remove fire




6. 基于ES6 发布订阅

let _subscribe = (function(){
    // SUB:发布订阅类 subscribe
    class Sub {
        constructor() {
            // 创建一个事件池,用来存储后期需要执行的方法
            this.$evPond = [];
        }

        // 向事件池中追加方法
        add(fun) {
            if(typeof fun === 'function'){
                let flag = this.$evPond.some(item => {return item === fun});
                if(!flag)this.$evPond.push(fun);
            }
        }

        // 从事件池中移除方法
        remove(fun) {
            if(typeof fun === 'function'){
                let index = this.$evPond.findIndex(item => item === fun);
                if(index>=0)this.$evPond[index] = null;
            }
        }

        // 通知事件池中的方法按照顺序依次执行 且把参数传进去
        fire(...args){
            //执行每一个方法
            try {
                this.$evPond.forEach((item, i, arr) => {
           			if(typeof item !== 'function'){
                        this.$evPond.splice(i,1);
           	        }
                    arr[i].call(this, ...args);
                }) 
            } catch (e) {
                if(e === new Error("StopIteration"))return;
                else throw e;
            }
        }
    }

    return function subscribe() {
        return new Sub();
    }
})();

// 一些事件
let fn1 = function(){
	console.log(1)
}
let fn2 = function(){
	console.log(2)
	pond.remove(fn1);
}
let fn3 = function(){
	console.log(3)
}
let fn4 = function(){
	console.log(4)
}
//创建一个事件池
let pond = _subscribe();
document.querySelector('.btn').onclick = function(ev){
	pond.fire();
}

pond.add(fn1);
pond.add(fn2);
pond.add(fn3);
pond.add(fn4);

你可能感兴趣的:(发布订阅模式)