定義
定義對(duì)象間的一種一對(duì)多的依賴(lài)關(guān)係兰迫,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴(lài)於它的對(duì)象都將得到通知炬称。在 JavaScript 中汁果,一般用事件模型來(lái)替代傳統(tǒng)的發(fā)佈-訂閱模式。
要點(diǎn)
- 發(fā)佈-訂閱模式的優(yōu)點(diǎn)非常明顯玲躯,一為時(shí)間上的解耦据德,二為對(duì)象之間的解耦。
- 在異步編程中使用發(fā)佈-訂閱模式府蔗,我們就無(wú)需過(guò)多關(guān)注對(duì)象在異步運(yùn)行期間的內(nèi)部狀態(tài)晋控,而只需要訂閱感興趣的事件發(fā)生點(diǎn)。
- DOM 事件
- 發(fā)佈-訂閱模式的實(shí)現(xiàn):首先指定好發(fā)佈者姓赤;給發(fā)佈者添加一個(gè)緩存列表赡译,用於存放回調(diào)函數(shù)來(lái)通知訂閱者;最後發(fā)佈消息的時(shí)候不铆,發(fā)佈者會(huì)遍歷這個(gè)緩存列表蝌焚,依次觸發(fā)裡面存放的訂閱者回調(diào)函數(shù)。
- 發(fā)佈-訂閱模式的通用實(shí)現(xiàn):event, installEvent
- 發(fā)佈-訂閱模式也可以用一個(gè)全局的 Event 對(duì)象來(lái)實(shí)現(xiàn)誓斥,訂閱者不需要瞭解消息來(lái)自哪個(gè)發(fā)佈者只洒,發(fā)佈者也不知道消息會(huì)推送給哪些訂閱者,Event 類(lèi)似一個(gè)「中介者」的角色劳坑。
- 發(fā)佈-訂閱模式還可以支持先發(fā)佈後訂閱和命名空間的功能毕谴。
核心代碼
var Event = (function() {
var clientList = {};
var listen;
var trigger;
var remove;
listen = function(key, fn) {
if (!clientList[key]) {
clientList[key] = [];
}
clientList[key].push(fn);
};
trigger = function() {
var key = Array.prototype.shift.call(arguments);
var fns = 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 = clientList[key];
if (!fns) {
return false;
}
if (!fn) {
// 移除全部訂閱
fns && (fns.length = 0);
} else {
for (var l = fns.length - 1; l >= 0; l--) {
var _fn = fns[l];
if (_fn === fn) {
fns.splice(l, 1);
}
}
}
};
return {
listen: listen,
trigger: trigger,
remove: remove
};
})();
Event.listen('ev1', function(param1, param2, ...) {
// callback
});
Event.trigger('ev1', param1, param2, ...);