将发布订阅的功能提取出来,放在一个单独的对象中
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); } }, }; var installEvent = function(obj){ for(var i in event){ obj[i] = event[i]; } } var salesOffices = {}; installEvent(salesOffices); salesOffices.listen('squareMeter88',function(price){ console.log("价格="+price); }); salesOffices.listen('squareMeter110',function(price){ console.log("价格="+price); }); salesOffices.trigger('squareMeter88',20000); salesOffices.trigger('squareMeter110',30000);
取消订阅事件
//取消订阅事件 event.remove=function(key,fn){ var fns=this.clientList[key]; if(!fns){ return false; } if(!fn){ fns&&(fns.length=0); }else{ for (var l = fns.length-1; l>=0; l--) { var _fn = fns[l]; if(_fn === fn){ fns.splice(l,1); } } } }
应用-真实的例子-网站登录
假如我们正在开发一个商城网站,网站中有header头部、nav导航、消息列表、购物车等模块。这几个模块的渲染有一个共同的前提条件,就是必须先使用ajax异步请求获取用户的登录信息。比如用户的名字和头像要显示在header模块中,而这两个字段都来自用户登录后返回的信息。
至于ajax请求什么时候能成功返回用户信息,没有办法确定。
对用户信息感兴趣的业务模块将自行订阅登录成功的消息事件。当登陆成功时,登录模块只需要发布登录成功的消息,而业务方接受消息后,就会开始进行各自的业务处理,登录模块并不关心业务方要做什么,也不需要了解他们的内部细节。改善后的代码如下:
$.ajax('http://xxx.com?login',function() { //登录成功 login.trigger('loginSucc',data); //发布登录成功的消息 }); //各模块监听成功的消息 var header=(function(){ login.listen('loginSucc',function(data){ //header模块 header.setAvatar(data.avatar); }); return { setAvatar:function(data){ console.log('设置header模块的头像'); } } })(); var nav=(function(){ //nav模块 login.listen('loginSucc',function(data){ nav.setAvatar(data.avatar); }); return { setAvatar:function(avatar){ console.log('设置nav模块的头像'); } } })();
如上所述,我们可以随时把setAvatar的方法名改成setTouxiang。如果有一天在登录完成之后,又增加一个刷新收货地址列表的行为,那么只要在收货地址模块里加上监听消息的方法即可,而这可以让开发该模块的同事自己完成,你作为登录模块的开发者,永远不用再关心这些行为了。
var address=(function(){ login.listen('loginSucc',function(data){ address.refresh(obj); }); return { refresh:function(avatar){ console.log('刷新收货地址列表'); } } })();
本人学习整理,非原创