// 发布-订阅模式的通用实现
//首先把发布订阅的功能提取出来, 放在一个单独的对象内
var event = {
clientList: [],
listen: function(key, fn) {
if (!this.clientList[key]) {
this.clientList[key] = [];
}
this.clientList[key].push(fn); // 订阅的消息添加进缓存列表
},
trigger: function() {
var key = Array.prototype.shift.call(arguments),
fns = this.clientList[key];
if (!fns || fns.length === 0) {
// 如果没有绑定对应的消息
return false;
}
for (var i = 0, fn; (fn = fns[i++]); ) {
fn.apply(this, arguments); // arguments 是 trigger 时带上的参数
}
}
};
// 取消订阅的事件
event.remove = function(key, fn) {
var fns = this.clientList[key];
if (!fns) { // 如果 key 对应的消息没有被人订阅, 则直接返回
return false;
}
if (!fn) { // 如果没有传入具体的回调函数, 表示需要取消 key 对应消息的所有订阅
fns && (fns.length = 0);
} else {
for (var l = fns.length - 1; l >= 0; l--) { // 反向遍历订阅的回调函数列表
var _fn = fns[l];
if (_fn === fn) {
fns.splice(1, 1); // 删除订阅者的回调函数
}
}
}
};
// 在定义一个 installEvent 函数 , 这个函数可以给所有的对象都动态安装发布订阅功能
var installEvent = function(obj) {
for (var i in event) {
obj[i] = event[i];
}
};
// 再来测试一番, 我们给售楼处对象 saleOffieces 动态增加发布-订阅功能
var saleOffieces = {};
installEvent(saleOffieces);
saleOffieces.listen(
"squareMeter88",
(fn1 = function(price) {
// 小明订阅的消息
console.log("价格price=" + price);
})
);
saleOffieces.listen(
"squareMeter110",
(fn2 = function(price) {
// 小红订阅的消息
console.log("价格price=" + price);
})
);
saleOffieces.remove("squareMeter88", fn1);
saleOffieces.trigger("squareMeter110", 110);