JavaScript设计模式 - 订阅发布模式(观察者模式)
var Event = (function() { var global = this, Event, _default = 'default'; Event = function() { var _create, _listen, _trigger, _remove, _shift = Array.prototype.shift, _unshift = Array.prototype.unshift, namespaceCache = {}, each = function(ary, fn) { var ret; for (var i = 0, l = ary.length; i < l; i ++) { var n = ary[i]; ret = fn.call(n, i, n); }; return ret; }; _listen = function(key, fn, cache) { if (!cache[key]) { cache[key] = []; }; cache[key].push(fn); }; _trigger = function() { var cache = _shift.call(arguments), key = _shift.call(arguments), args = arguments, _self = this, stack = cache[key]; if (!stack || !stack.length) return; return each(stack, function() { return this.apply(_self, args); }); }; _remove = function(key, cache, fn) { if (cache[key]) { if (fn) { for (var i = cache[key].length; i >= 0; i--) { if (cache[key][i] === fn) { cache[key].splice(i, 1); }; }; } else { cache[key] = []; }; }; }; _create = function(namespace) { var namespace = namespace || _default; var cache = {}, offlineStack = [], ret = { listen: function(key, fn, last) { _listen(key, fn, cache); if (offlineStack === null) return; if (last === 'last') { offlineStack.length && offlineStack.pop()(); } else { each(offlineStack, function() { this(); }); }; offlineStack = null; }, trigger: function() { var fn, args, _self = this; _unshift.call(arguments, cache); args = arguments; fn = function() { return _trigger.apply(_self, args); }; if (offlineStack) { return offlineStack.push(fn); }; return fn(); }, remove: function(key, fn) { _remove(key, cache, fn); }, one: function(key, fn, last) { _remove(key, cache); this.listen(key, fn, last); } }; return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret; }; return { create: _create, one: function(key, fn, last) { var event = this.create(); event.one(key, fn, last); }, remove: function(key, fn) { var event = this.create(); event.remove(key, fn); }, listen: function(key, fn, last) { var event = this.create(); event.listen(key, fn, last); }, trigger: function() { var event = this.create(); event.trigger.apply(this, arguments); } }; }(); return Event; })();
使用姿势:
/*// 先发布后订阅 event.trigger('evt1', 1, 2); event.trigger('evt1', 3, 4); // 都存到offlineStack中去了 event.listen('evt1', e1); // 当有listen监听时,遍历offlineStack中的方法,发给第一次的listen event.listen('evt1', e2);*/ /*// 先订阅后发布 event.listen('evt1', e1); event.listen('evt1', e2); // 先订阅的事件都存到cache对象中去了 event.trigger('evt1', 1, 2); // 每次发布,都会遍历cache对象中对象事件名的数组 event.trigger('evt1', 3, 4); */ /*// 先发布后订阅 listen方法第三个参数可以是last,只有只会去多个trigger中的最后一个 event.trigger('evt1', 1, 2); // 1). event.trigger('evt1', 3, 4); // 2). 都存到offlineStack中去了 event.listen('evt1', e1, 'last'); // 只会收到2).这个trigger*/ /*// 先订阅后发布再删除然后再发布,会发现evt1事件对象的cache[key]数组中少了e1函数,所以 // 再次发布只有e2执行了 event.listen('evt1', e1); event.listen('evt1', e2); event.trigger('evt1', 1, 2); event.remove('evt1', e1); event.trigger('evt1', 3, 4);*/ // 订阅的再多,也只使用一个订阅 /*// 1). 先订阅后发布 event.one('evt1', e1); event.one('evt1', e2); // 会使用这个,因为前一个被删了 event.trigger('evt1', 11, 22); // 所以会执行两次e2函数 event.trigger('evt1', 33, 44);*/ // 2). 先发布后订阅 /*event.trigger('evt1', 11, 22); // 所以会执行两次e2函数 event.trigger('evt1', 33, 44); event.one('evt1', e1); // 会使用这个,因为offlineStack被置为null了 event.one('evt1', e2); // 这个不执行了,需要等到下次trigger才会触发,因为e1从cache中删掉了,加入了e2, 如果后面还有one方法以此类推,会删除上一个监听的函数,添加新的监听函数*/ // 3). 先发布后订阅 one方法的第三个参数last会只接收最后一个trigger event.trigger('evt1', 11, 22); event.trigger('evt1', 33, 44); event.one('evt1', e2, 'last'); event.one('evt1', e1, 'last');
开心的做一个无忧无虑的码农,争取每天进步一点。