>[success] # 封装一个全局的发布订阅对象 ~~~ 1.假设我们有3个js文件,事件触发在a.js内,而响应该事件的在b.js和c.js内, 要是用常规调用的方法的话,就要把b.js和c.js的方法传到a.js内。这是一个非常麻烦 的操作。而发布-订阅模式是将调度中心挂在了全局,我们只管调用调度中心相应的方法注册和订阅。 2.这样就可以做到全局通信,甚至跨模块通信 ~~~ >[danger] ##### 封装成全局 ~~~ var Event = (function(){ var clientList = {}, listen, trigger, remove; listen = function( key, fn ){ if ( !clientList[ key ] ){ clientList[ key ] = []; } clientList[ key ].push( fn ); }; trigger = function(){ var key = Array.prototype.shift.call( arguments ), fns = clientList[ key ]; if ( !fns || fns.length === 0 ){ return false; } for( var i = 0, fn; fn = fns[ i++ ]; ){ fn.apply( this, arguments ); } }; remove = function( key, fn ){ var fns = 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 ); } } } }; return { listen: listen, trigger: trigger, remove: remove } })(); Event.listen( 'squareMeter88', function( price ){ // 小红订阅消息 console.log( '价格= ' + price ); // 输出:'价格=2000000' }); Event.trigger( 'squareMeter88', 2000000 ); // 售楼处发布消息 ~~~ >[danger] ##### 将上面代码转换成es6 ~~~ 1.其实这里可以考虑单例模式,全局共享一个实例,这里就没有具体改成单例模式, 详细的可以根据单例模式自己改进 ~~~ ~~~ /** * 1.发布者需要一个缓存列表 * 2.需要一个登记需要订阅对象的方法 * 3.需要一个发布消息的方法 * 4.需要一个删除不在需要订阅的方法 * **/ class Event{ constructor(){ this.clientList = {} } // 保存订阅对象方法 listen(key,fn){ if(!this.clientList[key]){ this.clientList[key] = [] } this.clientList[key].push(fn) } trigger(key,...args){ let fns = this.clientList[key] if(!fns || fns.length === 0){ return false } fns.forEach(fn=>{ fn(...args) }) } remove(key, fn){ let fns = this.clientList[key] if(!fns){ return false } // 如果不指定要删除的就默认删除全部 if(!fn){ fns && 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 ); } } } } } ~~~