手撸一个事件订阅器
AymaxLi opened this issue · comments
代码
function EventEmitter() {
// 依赖队列集
this.dep = {
// name1: [{
// once: true,
// fn: fn
// }],
// name2: [{
// once: true,
// fn: fn
// }]
}
}
EventEmitter.prototype.on = function (name, fn, once) {
var obj = {
fn,
once: once || false // 是否为 once,默认为 false
}
this.dep[name] ? this.dep[name].push(obj) : this.dep[name] = [obj] // 是否存在事件 name 的依赖队列,是则 push ,否则新建一个数组
}
EventEmitter.prototype.once = function (name, fn) {
this.on(name, fn, true)
}
EventEmitter.prototype.emit = function (name) {
var args = Array.prototype.slice.call(arguments, 1)
var onceArr = [] // 记录这次事件中 once 的函数
this.dep[name].forEach((el, index) => {
el.fn.apply(null, args) // 执行函数
// 假如是 once ,标记
if (el.once === true) onceArr.push(index)
})
// 移除 once 的函数
onceArr.forEach(index => this.dep[name].splice(index, 1))
}
EventEmitter.prototype.remove = function (name, fn) {
var index = this.dep[name].findIndex(el => el.fn.name === fn.name) // 找到要 remove 的函数的下标
this.dep[name].splice(index, 1) // 移除
}
测试用例
const sayOne = _ => console.log('one')
const sayTwo = _ => console.log('two')
const sayNo = _ => console.log('no')
// 测试 emit
;(_ => {
var e = new EventEmitter()
e.on('haha', console.log)
e.emit('haha', 'hei i am aymax')
})()
// 测试 once
;(_ => {
var e = new EventEmitter()
e.on('haha', sayOne)
e.on('haha', sayTwo)
e.once('haha', sayNo)
e.emit('haha')
e.emit('haha')
})()
// 测试 remove
;(_ => {
var e = new EventEmitter()
e.on('haha', sayOne)
e.on('haha', sayTwo)
e.once('haha', sayNo)
e.remove('haha', sayNo)
e.emit('haha')
e.remove('haha', sayOne)
e.emit('haha')
})()