Appearance
一个发布订阅模式实现
js
/**
* 发布订阅模式
*/
const Event = (function () {
var _global = this,
_default = 'default';
/**
* 需要有 listen trigger remove create
*/
return (function () {
// 定义模式
var _listen, _trigger, _remove, _create;
// 定义方法
var _shift = Array.prototype.shift, _unshift = Array.prototype.unshift, _slice = Array.prototype.slice;
var each = function (arr, fn) {
var ret;
for (var index = 0; index < arr.length; index++) {
var item = arr[index];
ret = fn.call(item, index, item);
}
return ret;
}
// 定义空间
var namespaceCache = {};
_listen = function (cache, key, fn) {
if (!cache[key]) {
cache[key] = [];
}
cache[key].push(fn);
}
_trigger = function () {
var cache = _shift.call(arguments),
key = _shift.call(arguments),
args = arguments,
stack = cache[key],
_self = this;
if (!stack || stack.length === 0) {
return;
}
return each(stack, function () {
return this.apply(_self, args);
})
}
_remove = function (cache, key, fn) {
if (cache[key]) {
cache[key].forEach(function (item, index) {
if (item === fn) {
cache[key].splice(index, 1);
}
});
} else {
cache[key] = [];
}
}
_create = function (namespace) {
var namespace = namespace || _default;
var cache = {},
offlineStack = []; // 离线时间
var ret = {
listen: function (key, fn, last) {
_listen(cache, key, fn);
// 如果离线时间栈是null,则之间听,否则需要将事件放入离线栈
if (offlineStack === null) {
return;
}
// 表明执行最后一个事件
if (last === 'last') {
offlineStack.length && offlineStack.pop()();
} else {
each(offlineStack, function () {
return this();
})
}
offlineStack = null;
},
one: function (key, fn, last) {
this.remove(key, fn);
this.listen(key, fn, last);
},
remove: function (key, fn) {
_remove(cache, key, fn);
},
trigger: function () {
var fn, args, _self = this;
// 将cache放入首位
_unshift.call(arguments, cache);
args = arguments;
fn = function () {
return _trigger.apply(_self, args);
};
// 如果有离线事件,则放进去
if (offlineStack) {
return offlineStack.push(fn);
}
return fn();
}
}
return namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = 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);
}
}
}())
}())
Event.trigger('click', 1);
Event.listen('click', function (a) {
console.log(a);
})
Event.create('name').listen('click', function (a) {
console.log('name', a);
})
Event.create('name').trigger('click', 1);
Event.create('name2').trigger('click', 1);
setTimeout(function () {
Event.create('name2').listen('click', function (a) {
console.log('name2', a);
})
}, 1000);