We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
自定义事件
var obj = {}; obj.eventList = []; obj.listen = function(fn) { obj.eventList.push(fn); }; obj.trigger = function() { for(var i = 0, fn; fn = this.eventList[i++];) { fn.apply(this, arguments); } };
增加标示 key
var obj = {}; obj.eventList = []; obj.listen = function(key, fn) { if (!this.eventList[key]) { this.eventList[key] = []; } obj.eventList[key].push(fn); }; obj.trigger = function() { var key = Array.prototype.shift.call(arguments); var fns = this.eventList[key]; if (!fns || !fns.length) { return false; } for(var i = 0, fn; fn = fns[i++];) { fn.apply(this, arguments); } };
发布-订阅的通用实现
var event = { eventList: [], listen: function(key, fn) { if (!this.eventList[key]) { this.eventList[key] = []; } this.eventList[key].push(fn); }, trigger: function() { var key = Array.prototype.shift.call(arguments); var fns = this.eventList[key]; if (!fns || !fns.length) { 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]; } };
取消订阅的事件:增加一个 remove 函数
remove
event.remove = function(key, fn) { var fns = this.eventList[key]; // 如果 key 对应的事件没有被订阅,则直接返回 if (!fns) { return false; } // 如果没有指定某个特定的函数,则全部移除 if (!fn) { this.eventList[key].length = 0; // 数组的 length 属性直接置为零 } else { // 倒序删除 for (var i = fns.length - 1; i >= 0; i--) { var _fn = fns[i]; if (_fn === fn) { fns.splice(i, 1); } } } };
一次实际应用:登录框
异步登录后,一般会触发页面上多个模块的动作,但在后面的需求中,又可能不知道哪些模块会增减。这种情况下可以用发布-订阅模式解决。
原始写法:
loginSuccess(function() { header.init(); nav.init(); footer.init(); sidebar.init(); });
这种情况下,万一后面新增了了一个模块,比如购物车 shopBar 也依赖登录状态的改变,那么就要在原来的代码里增加 shopBar.init() 的逻辑了。
shopBar
shopBar.init()
然而,其实登录只需要发布登录成功的消息,其他模块订阅该消息即可,登录模块不需要关心业务逻辑。
改造如下:
// 发布 $.ajax('xxx', function(data) { login.trigger('loginSuccess', data); }); // 订阅 var header = (function() { login.listen('loginSuccess', function(data) { header.init(data); }); return { init: function() { console.log('header init'); } }; })(); var nav = (function() { login.listen('loginSuccess', function(data) { nav.init(data); }); return { init: function() { console.log('nav init'); } }; })();
必须先订阅后发布吗?
当然不是,可以先发布后订阅。
当发布的时候,如果没有函数订阅,可以先缓存到一个函数里,有函数订阅的时候直接触发执行,而且只执行一次。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
自定义事件
增加标示 key
发布-订阅的通用实现
再加一个包装函数
取消订阅的事件:增加一个
remove
函数一次实际应用:登录框
异步登录后,一般会触发页面上多个模块的动作,但在后面的需求中,又可能不知道哪些模块会增减。这种情况下可以用发布-订阅模式解决。
原始写法:
这种情况下,万一后面新增了了一个模块,比如购物车
shopBar
也依赖登录状态的改变,那么就要在原来的代码里增加shopBar.init()
的逻辑了。然而,其实登录只需要发布登录成功的消息,其他模块订阅该消息即可,登录模块不需要关心业务逻辑。
改造如下:
必须先订阅后发布吗?
当然不是,可以先发布后订阅。
当发布的时候,如果没有函数订阅,可以先缓存到一个函数里,有函数订阅的时候直接触发执行,而且只执行一次。
The text was updated successfully, but these errors were encountered: