学习JavaScript设计模式之观察者模式
前端之家收集整理的这篇文章主要介绍了
学习JavaScript设计模式之观察者模式,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
一、定义
观察者模式(发布-订阅模式):其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
在JavaScript中,一般使用事件模型来替代传统的观察者模式。
好处:
- (1)可广泛应用于异步编程中,是一种替代传递回调函数的方案。
- (2)可取代对象之间硬编码的通知机制,一个对象不用再显示地调用另外一个对象的某个接口。两对象轻松解耦。
二、DOM事件–观察者模式典例
需要监控用户点击document.body的动作,但是我们没有办法预知用户将在什么时间点击。
所以,我们订阅document.body上的click事件,当body节点被点击时,body节点便向订阅者发布这个消息!
// 可以多个
订阅者
document.body.addEventListener("click",function() {
console.log(2);
},false);
doucment.body.click();
某网站有header头部、nav导航、消息列表等模块。这几个模块的渲染都需要获取用户登陆信息。
(1)一般写法:
登录成功,渲染header、nav
header.setInfo(data.headerInfo);
nav.setInfo(data.navInfo);
}
}
});
(2)使用观察者模式,很轻松解耦!
<div class="jb51code">
<pre class="brush:js;">
$.ajax({
...,success: function(data) {
if(data.status === "success") {
// 登录成功,发布登陆成功消息
login.trigger("loginsuccess",data);
}
}
});
var header = (function() {
// 监听消息
login.listen("loginsuccess",function(data){
header.setInfo(data.headerInfo);
});
return {
setInfo: function(data) {
console.log("设置header信息");
}
};
})();
var nav = (function() {
login.listen("loginsuccess",function(data){
nav.setInfo(data.navInfo);
});
return {
setInfo: function(data) {
console.log("设置nav信息");
}
}
})();
三、通用观察者模式
<div class="jb51code">
<pre class="brush:js;">
/*
- 示例:
- Event.create("namespace1").listen('click',function(a){
- console.log(a);
- });
- Event.create("namespace1").trigger("click",1);
*/
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,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);
};
// 移除订阅
_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,last) {
_listen(key,cache);
if (offlineStack == null) {
return;
}
if (last === 'last') {
offlineStack.length && offlineStack.pop()();
} else {
each(offlineStack,function () {
this();
});
}
offlineStack = null;
},one: function (key,last) {
_remove(key,cache);
this.listen(key,last);
},remove: function(key,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,last) {
var event = this.create();
event.one(key,last);
},fn) {
var event = this.create();
event.remove(key,fn);
},listen: function(key,last) {
var event = this.create();
event.listen(key,trigger: function() {
var event = this.create();
event.trigger.apply(this,arguments);
}
};
}();
return Event;
})();