標(biāo)簽:JS 設(shè)計(jì)模式
讀書筆記鏈接:
- 《JS設(shè)計(jì)模式》讀書筆記(一)
- 《JS設(shè)計(jì)模式》讀書筆記(二)
- 《JS設(shè)計(jì)模式》讀書筆記(四)
- 《JS設(shè)計(jì)模式》讀書筆記(五)
- 《JS設(shè)計(jì)模式》讀書筆記(六)
- 《JS設(shè)計(jì)模式》讀書筆記(七-完結(jié))
訂閱發(fā)布模式
其實(shí)就是事件機(jī)制输枯,可以實(shí)現(xiàn)異步房维。
通用的事件函數(shù)(自己寫的)
var event = (function(){
var _nsList = {},
_defaultNs = '__default__';
function useNamespace(ns) {
if(ns === undefined && _nsList[_defaultNs]) return _nsList[_defaultNs];
if(_nsList[ns]) return _nsList[ns]
var method = {
sub: {},
preEvent: {}, // key:[[args],[args],...]
listen: function(key, fn) {
if(!this.sub[key]) {
this.sub[key] = [];
}
this.sub[key].push(fn);
// 如果有已經(jīng)發(fā)生了的事件就立刻執(zhí)行
if(this.preEvent[key]) {
this.preEvent[key].forEach(function(args, index){
fn.apply(fn, args)
})
this.preEvent[key] = null;
}
},
trigger: function() {
var args = [];
for(var i=0,l=arguments.length;i<l;i++){
args.push(arguments[i])
}
key = args.shift();
if(!this.sub[key]) {
// 預(yù)發(fā)布事件
if(!this.preEvent[key]) this.preEvent[key] = [];
this.preEvent[key].push(args)
} else if(this.sub[key].length > 0){
// 正常trigger
this.sub[key].forEach(function(fn, index){
fn.apply(fn, args);
});
}
},
once: function(key, fn) {
// 如果存在預(yù)發(fā)布的事件,那么就直接執(zhí)行琅锻,并且不用監(jiān)聽了
if(this.preEvent[key]) {
this.preEvent[key].forEach(function(args, index){
fn.apply(fn, args)
})
this.preEvent[key] = null;
return;
}
// 為了能夠外部調(diào)用remove來手動(dòng)刪除
if(!this.sub[key+'_once']) this.sub[key + '_once'] = [];
this.sub[key + '_once'].push(fn);
var that = this;
var onceFn = function() {
that.remove(key, onceFn, that.sub)
fn.apply(that, arguments)
}
this.listen(key, onceFn, this.sub)
},
remove: function(key, fn) {
if(!this.sub[key] || this.sub[key].length === 0) return;
if(!fn) this.sub[key] = [];
else {
for(var i=this.sub[key].length;i--;){
if(this.sub[key][i] === fn) {
this.sub[key].splice(i, 1);
return;
}
}
// 檢查once的監(jiān)聽列表
if(!this.sub[key+'_once'] instanceof Array) return;
for(i=0,l=this.sub[key+'_once'].length;i<l;i++){
if(this.sub[key+'_once'][i] === fn) {
this.sub[key].splice(i, 1);
return;
}
}
}
},
}
if(ns === undefined) return _nsList[_defaultNs] = method;
return _nsList[ns] = method;
}
return {
defaultNs: useNamespace(),
listen: function(key, fn) {
this.defaultNs.listen(key, fn)
},
once: function(key, fn) {
this.defaultNs.once(key, fn)
},
remove: function(key, fn) {
this.defaultNs.remove(key, fn)
},
trigger: function(key, args) {
this.defaultNs.trigger.apply(this.defaultNs, arguments)
},
useNamespace: useNamespace,
}
}())
// 預(yù)發(fā)布
event.trigger('test', 10,213)
// 監(jiān)聽
var test;
event.listen('test', test = function(num,num2){
console.log('testnum:',num,num2);
})
event.listen('test', function(msg){console.log(msg)})
event.once('test', function(msg){console.log('once', msg)})
// 觸發(fā)三個(gè)事件
event.trigger('test', 11,0)
// 刪除事件1
event.remove('test', test)
// 觸發(fā)事件2
event.trigger('test', 222, 222)
但這個(gè)模式也有缺點(diǎn),就是如果大量使用的話,會(huì)造成bug的跟蹤困難