美文网首页前端常用技术点
发布-订阅模式简述

发布-订阅模式简述

作者: 赵小空 | 来源:发表于2019-09-30 16:40 被阅读0次

    简介:

    发布-订阅模式可以取代对象之间硬编码的通知机制,一个对象不用再显式地调用另外一个对象的某个接口。发布-订阅模式让两个对象松耦合地联系在一起,虽然不太清楚彼此的细节,但这不影响它们之间相互通信。当有新的订阅者出现时,发布者的代码不需要任何修改;同样发布者需要改变时,也不会影响到之前的订阅者。只要之前约定的事件名没有变化,就可以自由地改变它们。

    简单实现:

    class Observer {
        constructor() {
            this.subscribers = {}
        }
        on(type, fn) {
            if (!Object.prototype.hasOwnProperty.call(this.subscribers, type)) {
              this.subscribers[type] = [];
            }
            this.subscribers[type].push(fn);
        }
        once(type,fn){
            let cb=(v)=>{
                fn(v);
                this.off(type,cb)
            }
            this.on(type,cb)
        }
        off(type, fn,isall=false) {
            let listeners = this.subscribers[type];
            if (!listeners || !listeners.length) return;
            isall?this.subscribers[type]=[]:this.subscribers[type] = listeners.filter(v => v !== fn );
        }
        emit(type, ...args) {
            let listeners = this.subscribers[type];
            if (!listeners || !listeners.length) return;
            listeners.forEach(fn => fn(...args));        
        }
    }
    
    let ob = new Observer();
    
    let click1=function (val){ console.log('这是click1事件=>',val)}
    let click2=function (val){ console.log('这是click2事件=>',val)}
    ob.on('click', click1);
    ob.on('click', click2);
    // 每个示例运行单独注释掉即可
    // 示例1: 一个事件绑定多个函数
    ob.emit('click', '我点击了哦');
    // 示例2: 关掉后绑定click1的不会执行 但是绑定click2的可以执行
    //如removeEventListener 一样 匿名函数此种写法无法解除
    // ob.off('click',click1) 
    // ob.emit('click', '我点击了哦');
    
    // 示例3:解除事件绑定的所有函数
    // ob.off('click',click1,true)
    // ob.emit('click', '我点击了哦');
    // 只执行一次的函数
    // let fitF=(v)=>{console.log('我执行了fit',v)}
    // ob.once('fit',fitF)
    
    // ob.emit('fit','我执行了')
    // // 下面2不会执行
    // ob.emit('fit','我执行2')
    

    为什么要使用Object.prototype.hasOwnProperty

    因为js没有将hasOwnProperty作为一个敏感词,所以我们很有可能将对象的一个属性命名为hasOwnProperty,这样一来就无法再使用对象原型的 hasOwnProperty 方法来判断属性是否是来自原型链。

    var foo = {    
    hasOwnProperty: function() {        return false;    },    
    bar: 'Here be dragons'
    }; 
    foo.hasOwnProperty('bar'); // 始终返回 false
    

    不能使用 该对象.hasOwnProperty 这种方法,怎么来解决这个问题呢?我们需要使用原型链上真正的 hasOwnProperty 方法

    ({}).hasOwnProperty.call(foo, 'bar'); // true
    // 或者:
    Object.prototype.hasOwnProperty.call(foo, 'bar'); // true
    

    相关文章

      网友评论

        本文标题:发布-订阅模式简述

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