自己封装订阅发布库

//基于es6自己封装发布订阅库 jQ中的发布订阅没有去重的功能
let _subscribe = function(){
    //SUB :发布订阅类
    class Sub{
        constructor(){
            //创建一个事件池,用来存储后期需要执行的方法
            this.$pond = [];
        }
        //给事件池追加方法(做重复处理)
        add(func){
            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];
                if(typeof item !== 'function'){
                    //此时再删除
                    $pond.splice(i,1);
                    i--;
                    continue;
                }
                item.call(this, ...args)
            }
        }
    }
    //暴露给外面用
    return function subscribe(){
        return new Sub();
    }
}();

//使用 let s1 = _subscribe();
//事件池中移出事件导致的数组塌陷问题:fire的时候通知事件执行时,拿循环的索引i去对应数组的下标,当有事件被移除时,数组发生变化,但是去对应的索引i继续去对应,会导致事件中某几项被跳过.
//解决:移除用假装移除,把当前项改成null,这样索引还是不变.真正移除在fire的时候去进行,此时fire时需检查执行的是否为function

 

posted @ 2019-10-12 18:56  存在的人  阅读(210)  评论(0编辑  收藏  举报