设计模式:订阅-发布模式以及Vue 中的 $on,$emit 的

2020-05-11  本文已影响0人  泰然自若_750f

什么是“订阅-发布模式”?

订阅-发布模式定义了对象之间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都可以得到通知。

订阅-发布模式” vs 观察者模式

订阅-发布模式和观察者模式概念相似,但在订阅-发布模式中,订阅者和发布者之间多了一层中间件:一个被抽象出来的信息调度中心。

https://www.jianshu.com/p/89d656db6548

代码实现

class Dep{
     
    constructor(){
        this.depsList=[];
    }
    /**
     * 订阅
     * @param {*} key 事件
     * @param {*} component 组件
     * @param {*} fn 回调
     */

    on(key,component,fn){
       
        if(typeof component!='object' || component===null)
        {
            throw TypeError('component 不合法');
        }
        let index=this.depsList.findIndex(item=>item.key===key);
        if(index>=0)
        {
            this.depsList[index].callbacks.set(component,fn);
        }
        else{
            var callbacks=new Map();
            callbacks.set(component,fn);
            this.depsList.push({key:key,callbacks:callbacks});

        }

    }
    /**
     * 发布
     * @param {}} key 
     * @param  {...any} props 
     */
    emit(key,...props){
        //debugger
         let deps=this.depsList.find(item=>item.key===key);
         if(!deps) return;
        
         for (let  [component,fn] of (deps.callbacks)) {
              fn.call(component,...props)
         
         }
    }
    /**
     * 取消订阅
     * @param {*} key 
     * @param {*} component 
     */
     remove(key,component){
         if(typeof component==='object' && component!=null)
         {
            let deps=this.depsList.find(item=>item.key===key);
            if(!deps) return;
            if(deps.callbacks.has(component))
            {
                deps.callbacks.delete(component);
            }
                 
         }
         else{

            let index=this.depsList.findIndex(item=>item.key===key);
            if(index!=-1)
            {
                this.depsList.splice(index,1)
            }
         }
     }
}

let dep=new Dep();

class A {

}
class B {

}
let a=new A();
let b=new B();
//A 组件订阅
dep.on('click',a,(...props)=>{
      
    console.log(`a 组件收到:${{...props}}`);
       
})

//B 组件订阅

dep.on('click',b,(...props)=>{
      
    console.log(`b 组件收到:${{...props}}`);
       
})
//发布时间
dep.emit('click',a,b);
//移除A 组件上的订阅
dep.remove('click',a);
//全部移除
dep.remove('click');

执行结果

image.png
上一篇下一篇

猜你喜欢

热点阅读