- 发布订阅模式又叫观察者模式,它定义一种一对多的依赖关系,
- 当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
document.body.addEventListener('click', function () { alert(1); }, false); document.body.addEventListener('click', function () { alert(2); }, false); document.body.addEventListener('click', function () { alert(3); }, false); document.body.click();
发布--订阅模式的通用实现
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); } }, remove: function (key,fn) { var fns = this.clientList[key]; if (!fns) { return false; } if (!fn) { fns && (fns.length = 0); } else { for (var i = fns.length-1; i >= 0; i--) { var _fn = fns[i]; if (_fn === fn) { fns.splice(i, 1); console.log("删除成功!"); } } } } }; //给所有对象设置发布-订阅功能 var installEvent = function (obj) { for (var i in event) { obj[i] = event[i]; } }; var salesOffices = {}; installEvent(salesOffices); //订阅 salesOffices.listen("89cm3",f1= function (price) { console.log("价格:"+price); }); salesOffices.listen("120cm3",f2= function (price) { console.log("价格:" + price); }); //发布 salesOffices.trigger("89cm3", 1200000); salesOffices.trigger("120cm3", 2200000); salesOffices.remove("89cm3", f1); salesOffices.trigger("89cm3", 1200000);
- 防止全局命名冲突再重构。
var Event = (function () { var global = this, Event, _default = 'default'; Event = function () { var _listen, _trigger, _remove, _slice = Array.prototype.slice, _shift = Array.prototype.shift, _unshift = Array.prototype.unshift, namespaceCache = {}, _create, find, each = function (ary, fn) { var ret; for (var i = 0; i < ary.length; i++) { var n = ary[i]; ret = fn.call(n, i, n); } return ret; }; _listen = function (key,cache,fn) { if (!cache[key]) { cache[key] = []; } cache[key].push(fn); }; _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] = []; } } }; _trigger = function () { var cache = _shift.call(arguments), key = _shift.call(arguments), args = arguments, _self = this, ret, stack = cache[key]; if (!stack || !stack.length) { return; } return each(stack, function () { return this.apply(_self, args); }); }; _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; }, one: function (key, fn, last) { _remove(key, cache); this.listen(key, fn, last); }, remove: function (key, fn) { _remove(key, cache, fn) }, 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(); } }; 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; })();