本文共 2979 字,大约阅读时间需要 9 分钟。
前言 现实中的发布-订阅模式
小明最近看上了一套房子,到了售楼处之后才被告知,该楼盘的房子早已售罄。好在售楼MM告诉小明,不久后还有一些尾盘推出,开发商正在办理相关手续,手续办好后就可以购买。但到底什么时候,目前还没有人知道。 于是小明记下了售楼处的电话,以后每天都会打电话过去询问是不是到了购买时间。除了小明,还有小红、小强、小龙也会每天向售楼处咨询这个问题。一个星期后,售楼MM决定辞职,因为厌倦了每天回答1000个相同内容的电话。 当然现实中没有这么笨的售楼公司,实际上故事是这样的:小明离开之前,把电话号码留在了售楼处。售楼MM答应他,新楼盘一推出就马上发信息通知小明。小红、小强、小龙也是一样,他们的电话号码都被记在售楼处的花名册上,新楼盘推出的时候,售楼MM会翻开花名册,遍历上面的电话号码,依次发送一条短信来通知他们。
一、最简单的例子
// 订阅信息document.body.addEventListener('click', function(){ alert(1);},false);// 订阅信息document.body.addEventListener('click', function(){ alert(2);},false);// 发布消息document.body.click();
document.body订阅了click事件,然后当它被点击(发布)的时候,接收到了信息。
二、发布-订阅模式的模式简单实现
// 定义售楼处var salesOffices = {};// 售楼花名册salesOffices.clientList = [];// 订阅售楼消息的函数salesOffices.listen = function (fn) { this.clientList.push(fn);}// 发布售楼消息的函数salesOffices.trigger = function () { // 遍历花名册,给留了电话号码的客户发送信息 for (var i = 0, fn; fn = this.clientList[i++];) { debugger; fn.apply(this, arguments); }}// 小明订阅售楼信息salesOffices.listen(function (price) { console.log('price=' + price);});// 小红订阅售楼信息salesOffices.listen(function (price) { console.log('price=' + price);});// 售楼处发布售楼信息salesOffices.trigger('squareMeter88', 200000);salesOffices.trigger('squareMeter110', 300000);
简单的发布-订阅模式存在一个缺陷:就是如果小明只想订阅88平米的楼盘,但是售楼处会把所有的楼盘信息都推送给了他。我们可以做得更智能一些,给订阅的函数多传一个参数,表明订阅者只订阅那一个消息。
三、发布-订阅模式的模式进阶实现
// 定义售楼处var salesOffices = {};// 定义客户花名册salesOffices.clientList = [];// 定义订阅方法salesOffices.listen = function (key, fn) { // 花名册登记哪些客户订阅哪些信息(根据key来区分) if (!this.clientList[key]) { this.clientList[key] = []; } this.clientList[key].push(fn);}salesOffices.trigger = function () { // 获取key,获取第一个参数 var key = Array.prototype.shift.call(arguments); var fns = this.clientList[key]; if (!fns || fns.length === 0) { return false; } for (var i = 0, fn; fn = fns[i++];) { fn.apply(this, arguments); }}// 小明定于88平米的楼盘salesOffices.listen('squareMeter88', function (price) { console.log('price=' + price);});// 小红定于100平米的楼盘salesOffices.listen('squareMeter100', function (price) { console.log('price=' + price);});// 售楼处发布楼盘信息salesOffices.trigger('squareMeter88', 2000000);salesOffices.trigger('squareMeter100', 3000000);
四、封装订阅-发布模式
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); var fns = this.clientList[key]; if (!fns || fns.length === 0) { return false; } for (var i=0,fn;fn=fns[i++];) { fn.apply(this, arguments); } }}function installEvent(obj) { for (var i in event) { obj[i] = event[i]; }}var salesOffices = {};installEvent(salesOffices);salesOffices.listen('squareMeter88', function(price) { console.log(`price=${price}`); });salesOffices.trigger('squareMeter88',200000);
转载地址:http://zlizo.baihongyu.com/