发布-订阅模式(观察者模式)

定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。在js中,一般用事件模型来替代传统的发布-订阅模式

// 将发布---订阅的功能提取出来
let event = {
  // 缓存列表,存放订阅者订阅的事件和其回调函数
  clientList:{},
  // 增加订阅者订阅的事件和回调函数
  listen(key,fn){
    if(!this.clientList[key]){
        //如果没有订阅过此类消息,则给该类消息创建一个缓存列表 
        this.clientList[key] = [];
    }
    // 将订阅消息添加进消息缓存列表
    this.clientList[key].push(fn);
  },
  // 发布消息
  on(...args){
    let key = args.shift(),
        fns = this.clientList[key];
    if( !fns || fns.length === 0 ){ //没有绑定对应消息
        return false;
    }
 
    for(let fn of fns){  //通知订阅该消息的所有订阅者
        fn.call(this,args); //args是trigger时带上的参数
    }
 
  },
  // 取消订阅
  off(key,fn){
      let fns = this.clientList[key];
      if(!fns){
          return false;  //key对应的消息没有被人订阅,直接返回
      }
      if(!fn){ //没有传入fn,则表示取消key对应消息的所有订阅
          fns && ( fns.length=0 )
      }else{
        let index = fns.findIndex(function(val){
            return val===fn;
        });
        fns.splice(index,1); //删除订阅者的回调函数
        console.log('success');
      }
  }
};
 
// 给所有对象都动态安装订阅-分布功能
let installEvent = obj=>{
  for( let key in event ){
      obj[key] = event[key];
  }
};
 
let salesOffice = {};
installEvent(salesOffice);
 
salesOffice.listen('square88',fn1=price=>console.log('price='+price));
salesOffice.listen('square88',fn2=price=>console.log('price='+price));
salesOffice.on('square88',8000);
salesOffice.off('square88',fn1);
salesOffice.on('square88',8000);
// 全局发布--订阅对象
let Event = {
  // 缓存列表,存放订阅者的回调函数
  clientList:{},
  // 增加订阅者--监听
  listen(key,fn){
    if(!this.clientList[key]){
        //如果没有订阅过此类消息,则给该类消息创建一个缓存列表 
        this.clientList[key] = [];
    }
    // 将订阅消息添加进消息缓存列表
    this.clientList[key].push(fn);
  },
  // 发布消息
  trigger(...args){
    let key = args.shift(),
        fns = this.clientList[key];
    if( !fns || fns.length === 0 ){ //没有绑定对应消息
        return false;
    }
 
    for(let fn of fns){  //通知订阅该消息的所有订阅者
        fn.call(this,args); //args是trigger时带上的参数
    }
 
  },
  // 取消订阅
  remove(key,fn){
      let fns = this.clientList[key];
      if(!fns){
          return false;  //key对应的消息没有被人订阅,直接返回
      }
      if(!fn){ //没有传入fn,则表示取消key对应消息的所有订阅
          fns && ( fns.length=0 )
      }else{
        let index = fns.findIndex(function(val){
            return val===fn;
        });
        fns.splice(index,1); //删除订阅者的回调函数
        console.log('success');
      }
  }
};
 
Event.listen('88',price=>console.log('price='+price));
Event.trigger('88',88888);
 
// 模块间通信,每次点击a模块里面的按钮,b模块显示按钮点击次数
// 将b订阅的事件添加到全局发布--订阅对象
let b=(()=>{
  let div = document.getElementById('show');
  Event.listen('add',count => div.innerHTML=count );
})()
// 通过a触发全局发布--订阅对象发布消息
let a = (()=>{
  let count = 0;
  let button = document.getElementById('count');
  button.addEventListener('click',()=>Event.trigger('add',count++))
})()

上面利用全局发布–订阅对象实现模块间通信

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值