Map实现
位操作符号>>>
// mitt
// 源码地址:https://github.com/developit/mitt
export default function mitt(all) {
all = all || new Map();
return {
all,
on (type, handler) {
// 查找 map中是否有这个key
const handlers = all.get(type);
// 存在就直接push
if (handlers) {
handlers.push(handler);
} else {
// 不存在就创建 value是一个数组
all.set(type, [handler]);
}
},
off (type, handler) {
const handlers = all.get(type);
if (handlers) {
if (handler) {
// 删除指定的 handler处理函数, 找到了 idx >>> 0 就是idx对应的索引
// 没找到 -1 变为 4294967295,原数组不会改变
handlers.splice(handlers.indexOf(handler) >>> 0, 1);
} else {
// 如果没有传对应的handler,则把此type的全部事件全部清除
all.set(type, [])
}
}
},
emit (type, evt) {
let handlers = all.get(type);
if (handlers) {
handlers.slice().map((handler) => {
handler(evt);
})
}
// 如果存在监听*的情况,则会将事件全部触发一次
handlers = all.get('*');
if (handlers) {
handlers.slice().map((handler) => {
handler(type, evt);
});
}
}
}
}
类实现
- 支持链式调用
- 支持自定义this
- once实现:执行监听方法后 执行off删除监听事件
//tiny-emitter
// 源码地址:https://github.com/scottcorgan/tiny-emitter
function E () {
// Keep this empty so it's easier to inherit from
// (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
}
E.prototype = {
on: function (name, callback, ctx) {
var e = this.e || (this.e = {});
(e[name] || (e[name] = [])).push({
fn: callback,
ctx: ctx
});
return this;
},
once: function (name, callback, ctx) {
var self = this;
function listener () {
self.off(name, listener);
callback.apply(ctx, arguments);
};
listener._ = callback
return this.on(name, listener, ctx);
},
emit: function (name) {
var data = [].slice.call(arguments, 1);
var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
var i = 0;
var len = evtArr.length;
for (i; i < len; i++) {
evtArr[i].fn.apply(evtArr[i].ctx, data);
}
return this;
},
off: function (name, callback) {
var e = this.e || (this.e = {});
var evts = e[name];
var liveEvents = [];
if (evts && callback) {
for (var i = 0, len = evts.length; i < len; i++) {
if (evts[i].fn !== callback && evts[i].fn._ !== callback)
liveEvents.push(evts[i]);
}
}
// Remove event from queue to prevent memory leak
// Suggested by https://github.com/lazd
// Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910
(liveEvents.length)
? e[name] = liveEvents
: delete e[name];
return this;
}
};
module.exports = E;
module.exports.TinyEmitter = E;