學習JavaScript設計模式之觀察者模式
一、定義
觀察者模式(發(fā)布-訂閱模式):其定義對象間一種一對多的依賴關系,當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都將得到通知。
在JavaScript中,一般使用事件模型來替代傳統(tǒng)的觀察者模式。
好處:
- (1)可廣泛應用于異步編程中,是一種替代傳遞回調(diào)函數(shù)的方案。
- (2)可取代對象之間硬編碼的通知機制,一個對象不用再顯示地調(diào)用另外一個對象的某個接口。兩對象輕松解耦。
二、DOM事件–觀察者模式典例
需要監(jiān)控用戶點擊document.body的動作,但是我們沒有辦法預知用戶將在什么時間點擊。
所以,我們訂閱document.body上的click事件,當body節(jié)點被點擊時,body節(jié)點便向訂閱者發(fā)布這個消息!
document.body.addEventListener("click", function() {
console.log(1);
}, false);
// 可以多個訂閱者
document.body.addEventListener("click", function() {
console.log(2);
}, false);
doucment.body.click();
某網(wǎng)站有header頭部、nav導航、消息列表等模塊。這幾個模塊的渲染都需要獲取用戶登陸信息。
(1)一般寫法:
$.ajax({
url: './login',
type: 'post',
contentType: 'application/json',
dataType:'json',
success: function(data) {
if(data.status === "success") {
// 登錄成功,渲染header、nav
header.setInfo(data.headerInfo);
nav.setInfo(data.navInfo);
}
}
});
(2)使用觀察者模式,很輕松解耦!
$.ajax({
...,
success: function(data) {
if(data.status === "success") {
// 登錄成功,發(fā)布登陸成功消息
login.trigger("loginsuccess", data);
}
}
});
var header = (function() {
// 監(jiān)聽消息
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信息");
}
}
})();
三、通用觀察者模式
/*
* 示例:
* 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] = [];
}
}
};
// 發(fā)布
_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);
});
};
// 創(chuàng)建命名空間
_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, last) {
_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;
})();
希望本文所述對大家學習javascript程序設計有所幫助。
- JavaScript觀察者模式原理與用法實例詳解
- 原生javascript實現(xiàn)類似vue的數(shù)據(jù)綁定功能示例【觀察者模式】
- PHP觀察者模式實例分析【對比JS觀察者模式】
- JavaScript設計模式之觀察者模式實例詳解
- JavaScript設計模式之觀察者模式(發(fā)布訂閱模式)原理與實現(xiàn)方法示例
- JS設計模式之觀察者模式實現(xiàn)實時改變頁面中金額數(shù)的方法
- JavaScript原生實現(xiàn)觀察者模式的示例
- JavaScript編程設計模式之觀察者模式(Observer Pattern)實例詳解
- javascript觀察者模式實現(xiàn)自動刷新效果
- JavaScript觀察者模式(publish/subscribe)原理與實現(xiàn)方法
- 深入理解Javascript中的觀察者模式
- Javascript設計模式之觀察者模式(推薦)
- JavaScript觀察者模式(經(jīng)典)
- 怎樣用JavaScript實現(xiàn)觀察者模式
相關文章
關于ckeditor在bootstrap中modal中彈框無法輸入的解決方法
今天小編就為大家分享一篇關于ckeditor在bootstrap中modal中彈框無法輸入的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09
javascript框架設計讀書筆記之模塊加載系統(tǒng)
本文是司徒正美的《javascript框架設計》的第二章模塊加載系統(tǒng)的讀書筆記,根據(jù)自己的理解,簡要的跟大家講述了本章的主要內(nèi)容,方便大家更好的學習。2014-12-12
JavaScript詞法作用域與調(diào)用對象深入理解
關于 Javascript 的函數(shù)作用域、調(diào)用對象和閉包之間的關系很微妙,關于它們的文章已經(jīng)有很多,本文做了一些總結(jié),需要的朋友可以參考下2012-11-11

