美文网首页
js 发布订阅设计模式(观察者模式)

js 发布订阅设计模式(观察者模式)

作者: 看庭前花开花落_望天上云卷云舒 | 来源:发表于2020-01-19 17:00 被阅读0次
    一、DOM0和DOM2的核心知识

    1、语法上的区别

        box.onclick=function(){}
        box.addEventListener('click',function(){})
    

    2、底层运行机制上的区别
    DOM0就是给元素的某个属性绑定方法(有效绑定的方法只有一个)
    DOM2是基于事件池机制完成,每增加一个绑定的方法,都会往事件池中存放一个...当事件触发会一次执行事件池中的事情
    =》发布订阅其实就是模拟的事件池机制(可以给同一个元素的某个事件绑定多个不同的方法)
    3、dom2中可以给一些特殊的事件类型绑定方法,这些事件类型DOM0不支持绑定,例如:DOMContentLoaded、transitionend...

    $(document).ready()=>$(function(){})
    vs
    window.onload 
    //二者的区别:
    //前者相当于DOM2事件绑定,可以绑定多次 后者相当于dom0事件绑定 只能绑定一次;
    //前者触发条件是dom加载完毕就开始触发 后者触发条件是dom结构和所有的元素都加载完成了开始触发
    

    DOM2的事件池机制:
    1、基于addEventListener/attachEvent(IE6-8)向事件池中追加方法:
    新版本浏览器会根据元素和事件类型对新增的方法做重复校验,但是IE6-8不可以
    2、当事件行为触发,会把事件池中的方法按照增加的顺序依次执行,但是IE6-8中执行的顺序不固定

    二、jquery中发布订阅处理
    <button class="submit">点我啊。。。</button>
    let fn1=function(){
       console.log(1)
    }
    let fn2=function(){
       console.log(2)
    }
    let fn3=function(){
       console.log(3)
    }
    $('.submit').click(function(){
       fn1();
       fn2();
       fn3();
    })
    //1
    //2
    //3
    

    三、基于ES6自己封装发布订阅库

    //.构造函数模式
    //.整体思路的实现
    //.数组塌陷问题和解决办法
    
    let _subscribe=(function(){
        //=>Sub:发布订阅类
        class Sub{
            //=>创建一个事件池,用来存储后期需要执行的方法
            constructor(){
                this.$pond=[];
            }
            //=>向事件池中追加方法(需要去重)
            add(func){
                //=>判断数组中是否存在相同的有相同的会返回来true
                let flag=this.$pond.some(item=>{
                    return item===func
                });
                !flag?this.$pond.push(func):null;
            }
            //=>从事件池中移除方法:同时需要解决数据塌陷问题
            remove(func){
                let $pond=this.$pond;
                for(let i=0;i<$pond.length;i++){
                    let item = $pond[i];
                    if(item === func){
                        //=>移除(顺序不变的情况下基本只能用SPLICE了),但是不能这样写,这样会导致数组塌陷问题
                        //我们移除不能真移除,只能把当前项赋值未null,执行的时候我们再删除
                        //$pond.splice(i,1);
                        $pond[i]=null;
                        break;
                    }
                }
            }
            //=>通知事件池中的方法,按照顺序依次执行,执行的时候还可以给每一个方法传递参数
            fire(...args){
                let $pond=this.$pond;
                for(let i=0;i<$pond.length;i++){
                    let item=$pond[i];
                    //让每一个方法中的this还是当前类的实例,
                    if(typeof item !=='function'){
                        //=>此时再删除
                        $pond.splice(i,1);
                        i--;
                        continue;
                    }
                    item.call(this,...args);
                }
            }
        }
        //=>把Sub这个类暴露出去,new Sub()这样创建一个类的实例的时候就不用 new Sub()了,直接执行_subscribe
        return function subScribe(){
            return new Sub()
        }
    })();
    
    

    使用自己封装的方法库

    <button class="submit">点我啊。。。</button>
    let pond=_subscribe();
    document.querySelector('.submit').onclick=function(ev){
        pond.fire(ev);
    };
    let fn1=function(){
        console.log(1)
    }
    let fn2=function(){
        console.log(2);
        pond.remove(fn1);
    }
    let fn3=function(){
        console.log(3)
    }
    let fn4=function(ev){
        console.log(4)
    }
    pond.add(fn1);
    pond.add(fn2);
    pond.add(fn3);
    pond.add(fn4);
    
    //打印结果:第一次点击结果:1 2 3 4
    // 第一次点击结果:2 3 4
    
    

    注:笔记源与珠峰培训

    相关文章

      网友评论

          本文标题:js 发布订阅设计模式(观察者模式)

          本文链接:https://www.haomeiwen.com/subject/odvrzctx.html