/** * 简单的事件通知实现;具体使用时,可以封装到自己的项目内; * * 主要用于同一个页面上的跨JS文件、跨模块之间的事件通信; * * 当页面内多个相对较为独立的模块之间需要有一些交互时, * 传统的回调形式会增加模块与模块之间的耦合,采用事件通知 * 机制,可以有效的降低页面之间的耦合度;是开发低耦合模块 * 化页面必不可少的一个简单技巧; * * @author zhoujq861124@gmail.com * * @example * listener.define('com.myTest'); * * A模块内监听'com.myTest'频道下的say事件 * listener.on('com.myTest', 'say', function(d){alert(d);}); * * B模块内触发'com.myTest'频道下的say事件 * listener.fire('com.myTest', 'say', 'Hello World!'); */ var listener = (function(){ var that = {}, channelList = window.channelList || {}, //用于保存被注册过所有频道 fireList = [], //用于保存所有需要被fire的任务 timer = ''; /** * 简单的防止密集运算的fire函数队列执行 */ var runFireList = function(){ if(fireList.length == 0){ return; } clearTimeout(timer); var curTask = fireList.shift(); try{ curTask['func'].apply(curTask['func'], [].concat(curTask['data'])); }catch(exp){ $.log('listener: One of ' + curTask['type'] + '`s function execute error!'); } timer = setTimeout(runFireList, 25); } /** * 通知定义,所有的通知都必须预先定义, * 才可以进行相应频道的事件注册; * 注:统一注册,便于管理 * @param {String} channel * @param {String} type */ var define = function(channel){ if(channelList[channel]){ throw 'Channel[ ' + channel + ' ] has been used!'; } channelList[channel] = {}; }; /** * 通知监听 * @param {String} channel 频道名 * @param {String} type 事件类型 * @param {Function} callback 事件响应 */ var on = function(channel, type, callback){ var curChannel = channelList[channel]; if(!curChannel){ throw 'Channel[ ' + channel + ' ] is undefined!'; } curChannel[type] = curChannel[type] || []; curChannel[type].push(callback); }; /** * 事件触发 * @param {String} channel * @param {String} type * @param {Object} data 要传递给相应函数的实参 */ var fire = function(channel, type, data){ if (channelList[channel] && channelList[channel][type] && channelList[channel][type].length > 0) { var taskList = channelList[channel][type]; for (var i = taskList.length; i--;) { fireList.push({ 'func': taskList[i], 'type': type, 'data': data }) } runFireList(); } }; /** * 事件监听移除 * @param {String} channel 频道名 * @param {String} type 事件类型 * @param {Function} callback 要移除的事件响应函数句柄 */ var remove = function(channel, type, cbHandler){ if (channelList[channel] && channelList[channel][type] && channelList[channel][type].length > 0) { var taskList = channelList[channel][type]; for (var i = taskList.length; i--;) { (taskList[i] === cbHandler) && taskList.splice(i, 1); } } }; that.define = define; that.on = on; that.fire = fire; that.remove = remove; return that; })();