一、核心概述
发布订阅模式主要包含三大块:缓存数组、订阅、发布
缓存数组 | 一个数组[] |
订阅 | 往数组里面压入函数fn |
发布 | 里面循环遍历数组,然后执行数组中的函数。 |
二、简单代码实现及改进
(1)实现
var subpub = {};
subpub.cache = [];
subpub.subscribe = function(fn){
this.cache.push(fn)
}
subpub.publish = function(){
for(var i in this.cache){
this.cache[i].apply(this,arguments)
}
}
//test
subpub.subscribe(function(price,square){
console.log("price:"+price)
console.log(square)
})
subpub.publish(200,102);
subpub.publish(300,153)
(2)改进 --- 主要针对订阅者不需要接收到所有的发布事件---key
var subpub = {};
subpub.cache = {}; //是一个数组对象
subpub.subscribe = function (key, fn) {
if (!this.cache[key]) { //订阅的事情在缓存里面没有,则添加到缓存
this.cache[key] = [];
}
this.cache[key].push(fn);
}
subpub.publish = function () {
//传入参数的第一个是指订阅的类型
var key = Array.prototype.splice.apply(arguments,[0,1]);
for (var i in this.cache[key]) {
this.cache[key][i].apply(this, arguments)
}
}
//test
subpub.subscribe('lowPrice',function (price, square) { //A订阅价格低于300的
console.log("price:" + price)
console.log(square)
})
subpub.subscribe('highPrice',function (price, square) { //B订阅价格高于300的
console.log("price:" + price)
console.log(square)
})
subpub.publish('lowPrice',200, 102);
subpub.publish('highPrice',400, 153)
取消订阅的事件
subpub.subscribe('lowPrice', fn1 = function (price, square) { //A订阅价格低于300的
console.log(square)
})
subpub.subscribe('lowPrice', fn11 = function (price, square) { //A订阅价格低于300的
console.log("price1:" + price)
console.log(square)
})
subpub.subscribe('highPrice', fn2 = function (price, square) { //B订阅价格高于300的
console.log("price:" + price)
console.log(square)
})
//取消订阅的事件
subpub.remove = function (key, fn) {
if (!this.cache[key]) { //如果key对应的消息没有被订阅,则直接返回
return false
}
if(!fn){ //如果没有传入fn,则移除key对应的所有消息
this.cache[key] && (this.cache[key].length=0)
} else {
this.cache[key] = this.cache[key].filter(function (cur, index) {
return cur !== fn
})
}
}
subpub.remove('lowPrice',fn1)
subpub.publish('lowPrice', 200, 102);
取消的时候,注意区分不同情况。上述使用了filter函数用来过滤需要取消订阅的事件
三、现实项目需求
网站登录====》登录以后需要在各处显示客户的信息。不能在用户登陆后去依次调用模块的刷新或或其他相关函数,要监听登录这一次操作。
//封装一下
var event = {
cache: {},
subscribe: function (key, fn) {
if (!this.cache[key]) { //订阅的事情在缓存里面没有,则添加到缓存
this.cache[key] = [];
}
this.cache[key].push(fn);
},
publish: function () {
//传入参数的第一个是指订阅的类型
var key = Array.prototype.splice.apply(arguments, [0, 1]);
for (var i in this.cache[key]) {
this.cache[key][i].apply(this, arguments)
}
},
remove: function (key, fn) {
if (!this.cache[key]) { //如果key对应的消息没有被订阅,则直接返回
return false
}
if (!fn) { //如果没有传入fn,则移除key对应的所有消息
this.cache[key] && (this.cache[key].length = 0)
} else {
this.cache[key] = this.cache[key].filter(function (cur, index) {
return cur !== fn
})
}
}
};
var eventForPub = function (obj) {
for (var i in event) {
obj[i] = event[i]
}
}
var login = {};
eventForPub(login)
var headItem = (function () {
login.subscribe('login', function (data) {
headItem.setAvatar(data.avatar)
})
return {
setAvatar: function (data) {
console.log("头部显示客户信息")
}
}
})();
var buyItem = (function () {
login.subscribe('login', function (data) {
buyItem.setAvatar(data.avatar)
})
return {
setAvatar: function (data) {
console.log("购物车显示客户信息")
}
}
})();
var data={avatar:'qqqq'}
login.publish('login',data);
运行结果如下: