定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。在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++))
})()
上面利用全局发布–订阅对象实现模块间通信