发布——订阅模式
发布—订阅模式在vue和node.js中广泛使用。
发布—订阅模式的需要 发布者(对象)、订阅者(函数)、订阅函数、触发函数
在vue中有这种代码:this.$on(); this.$emit();
在node.js中有这种代码:
var events = require('events');
var emitter = new events.EventEmitter();
emitter.on('someEvent', ()=>{});
emitter.on('someEvent', ()=>{});
emitter.emit('someEvent', 'arg1 参数', 'arg2 参数');
在原生js事件监听中有这种:
button.addEventListener('click',()=>{});
以上都是使用的发布订阅模式。
下面模拟一个事件监听器:
一 首先声明 发布者
var salesOffices = {};//发布者
salesOffices.clientList = [];//缓存列表,存放订阅者的回调函数
salesOffices.listen = function(sub){
this.clientList.push(sub);// 订阅的消息添加进缓存列表
}
salesOffices.trigger = function() {
this.clientList.forEach((sub) => {
sub.apply(this,arguments);
})
}
二 声明 订阅者
/* 声明订阅者 */
function sub1(msg) {
console.log("我是订阅者sub1",msg);
}
function sub2(msg) {
console.log("我是订阅者sub2",msg);
}
function sub3(msg) {
console.log("我是订阅者sub3",msg);
}
三 订阅 订阅者
/* 添加订阅者 */
salesOffices.listen(sub1);
salesOffices.listen(sub2);
salesOffices.listen(sub3);
四 触发 订阅者函数
/* 触发发布 */
salesOffices.trigger("我是发布的消息");
现在发布者发布的消息,全部订阅者都收的到,但是接下来我们要实现的是让不同的订阅者接受特定的消息,相当于click事件只能触发订阅了click事件的处理函数。并且添加了 移除订阅者 和 移除某类事件的订阅者 的函数。
var salesOffices = {};//发布者
salesOffices.clientList = {};//缓存列表,存放订阅者的回调函数
salesOffices.listen = function(key,sub){
if(!(this.clientList[key])){
this.clientList[key] = [];
}
this.clientList[key].push(sub);// 订阅的消息添加进缓存列表
}
salesOffices.trigger = function() {//发布消息
var key = Array.prototype.slice.call(arguments,0)[0];
//提高性能
if(!this.clientList[key] || this.clientList[key].length == 0){
return
}
this.clientList[key].forEach((sub) => {
sub.apply(this,arguments);
})
}
//移除订阅者
salesOffices.removeSubscriber = function(key,sub) {
if(!this.clientList[key] || this.clientList[key].length == 0){
return
}
const index = this.clientList[key].findIndex((element) => {return element == sub});
this.clientList[key].splice(index,1);
}
/* 移除一类事件的所有订阅者 */
salesOffices.removeAllSubscribers = function(key) {
if(!this.clientList[key] || this.clientList[key].length == 0){
return
}
delete this.clientList[key];
}
/* 声明订阅者 */
function sub1(key,msg) {
console.log("我是订阅者sub1",key,msg);
}
function sub2(key,msg) {
console.log("我是订阅者sub2",key,msg);
}
function sub3(key,msg) {
console.log("我是订阅者sub3",key,msg);
}
/* 添加订阅者 */
salesOffices.listen('click',sub1);
salesOffices.listen('click',sub2);
salesOffices.listen('mouseover',sub3);
/* 触发发布 */
salesOffices.trigger('click',"我是发布的消息");//sub3虽然被订阅,但是不会被执行
salesOffices.removeSubscriber('click',sub1);
salesOffices.trigger('click',"我是发布的消息");
salesOffices.removeAllSubscribers('click');
salesOffices.trigger('click',"我是发布的消息");