- 发布订阅模式又叫观察者模式,它定义一种一对多的依赖关系,
- 当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
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;})();