事件总线实现
RoleTang 7/25/2022
class mitt {
constructor() {
// 一个事件名 => 多个事件
this.tasks = {}
}
$emit(taskName, payload) {
const tasks = this.tasks[taskName]
// 存放当前一次性的 task
const removeTasks = []
if (tasks) {
tasks.forEach((cb) => {
cb(payload)
// 如果当前是只执行一次的函数,直接在执行之后将其关闭即可
if (cb.once) {
// 不能在这里执行删除,如果执行了,forEach循环就直接停止了
// this.$off(taskName, cb)
removeTasks.push(cb)
}
})
}
// 执行完毕后再进行删除
removeTasks.forEach((cb) => this.$off(taskName, cb))
}
$on(taskName, cb) {
if (!this.tasks[taskName]) {
this.tasks[taskName] = []
}
this.tasks[taskName].push(cb)
}
// 只执行一次
$once(taskName, cb) {
if (!this.tasks[taskName]) {
this.tasks[taskName] = []
}
// 直接在函数上进行标记
cb.once = true
this.tasks[taskName].push(cb)
}
$off(taskName, cb) {
const tasks = this.tasks[taskName]
if (tasks) {
for (let i = 0; i < tasks.length; i++) {
if (tasks[i] === cb) {
tasks.splice(i, 1)
// 改变了自身,i自减
i--
// 当是once时,直接跳出,防止多删
if (cb.once) break
}
}
}
}
}