发布-订阅模式定义对象间的一种 一对多 的依赖关系, 当一个对象的状态发生改变时, 所有依赖于它的对象都将得到通知简单实现 // 定义发布者 var salesOffices = {}; // 缓存列表, 存放订阅者的回调函数 salesOffices.clientList = []; // 定义订阅者 salesOffices.listen = function (fn) { this.clientList.push(fn); } // 发布消息 salesOffices.trigger = function () { for (var i = 0, fn; fn = this.clientList[i++];) { fn.apply(this, arguments) } } /*** 测试 ***/ // 订阅者1 salesOffices.listen(function (price, squareMeter) { console.log('价格=' + price); console.log('squareMeter= ' + squareMeter); }); // 订阅者2 salesOffices.listen(function (price, squareMeter) { console.log('价格=' + price); console.log('squareMeter= ' + squareMeter); }); // 发布消息 salesOffices.trigger(2000, 80); salesOffices.trigger(3000, 100);上面的实现方式, 导致了, 每个订阅者都会收到发布者发布的消息 // 定义发布者 var salesOffices = {}; // 缓存列表, 存放订阅者的回调函数 salesOffices.clientList = {}; // 定义订阅者 (增加缓存, 增加标示 key ) salesOffices.listen = function (key, fn) { if (!this.clientList[key]) { this.clientList[key] = []; } this.clientList[key].push(fn); } // 发布消息 salesOffices.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) } }提炼发布-订阅模式 // 核心事件 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); } } } // 取消订阅消息 event.remove = function (key, fn) { var fns = this.clientList[key]; if (!fns) { return false; } if (!fn) { // 没有传入fn 取消key对应的所有的订阅 fns && (fns.length = 0); } else { // 传入fn 删除对应的fn for (var l = fns.length - 1; l >= 0; l--) { var _fn = fns[l]; if (_fn === fn) { fns.splice(l, 1) } } } } // 给任何对象动态增加发布-订阅功能 var installEvent = function (obj) { for (var key in event) { if (event.hasOwnProperty(key)) { obj[key] = event[key]; } } } /*** 测试 ***/ var salesOffices = {}; installEvent(salesOffices); // 订阅者1 salesOffices.listen('squareMeter80', function (price) { console.log('价格=' + price); }); // 订阅者2 salesOffices.listen('squareMeter100', function (price) { console.log('价格=' + price); }); // 发布消息 salesOffices.trigger('squareMeter80', 20000); salesOffices.trigger('squareMeter100', 30000);登录案例 // 登录成功, 发布成功消息 $.ajax('http://xxx.com/login', function (data) { login.trigger('loginSuccess', data); }); // 这种写法也很好 var header = (function () { // 订阅消息 login.listen('loginSuccess', function (data) { header.setAvatar(data); }) return { setAvatar: function (data) { console.log('header 模块拿到用户信息') } } })();以上写法会有三个问题
...