文章原文: https://www.cnblogs.com/yalong/p/14294497.html
EventBus 幾個常用方法如下:
- on
- emit
- off
- once
這里用Map 存儲 EventBus 的數據,Map 的模擬實現 可以看 https://www.cnblogs.com/yalong/p/14292024.html
示例代碼如下:
let eb = new EventBus()
eb.on('event1', test1)
eb.emit('event1', '第一次')
eb.off('event1', test1)
eb.emit('event1', ['第二次1', '第二次2'])
eb.once('once', test4);
eb.emit('once', '執行一次', 1, 2, 3)
模擬實現代碼如下:
class EventBus {
constructor () {
this._events = new Map(); // 存儲事件/回調鍵值對
}
// on 監聽
on(type, fn) {
const handler = this._events.get(type); // 獲取對應事件名稱的函數清單
if (!handler) {
this._events.set(type, fn)
} else if (handler && typeof handler === 'function') {
// 如果handler是函數,說明當前只有一個監聽者
// 再次添加監聽者,需要改用 數組儲存
this._events.set(type, [handler, fn]);
} else {
// 已有多個監聽者,直接往數組里push函數即可
handler.push(fn);
}
}
// emit 觸發
emit(type, ...args) {
let handler = this._events.get(type)
if (Array.isArray(handler)) {
// 是數組,說明有多個監聽者,需要依次觸發里邊的函數
for (let i = 0; i < handler.length; ++i) {
if (args.length > 0) {
handler[i].apply(this, args)
} else {
handler[i].call(this);
}
}
} else {
// 單個函數的情況直接觸發即可
if (args.length > 0) {
handler.apply(this, args)
} else {
handler.call(this)
}
}
return true
}
// off 移除監聽
off(type, fn) {
const handler = this._events.get(type)
if (handler && typeof handler === 'function') {
// 函數,說明只有一個監聽者,直接刪除就行
this._events.delete(type)
} else {
handler.splice(handler.findIndex(e => e === fn), 1)
}
}
// 單次執行
once(type, fn) {
let _self = this
function handler() {
_self.off(type, handler)
fn.apply(null, arguments)
}
this.on(type, handler)
}
}
// 下面是 測試代碼
function test1 (...params) {
console.log(11, params)
}
function test2 (...params) {
console.log(22, params)
}
function test3 (...params) {
console.log(33, params)
}
function test4 (...params) {
console.log(params)
console.log(33, params)
}
//測試用例
let eb = new EventBus()
eb.on('event1', test1)
eb.on('event1', test2)
eb.on('event1', test3)
eb.emit('event1', '第一次')
eb.off('event1', test1)
eb.emit('event1', ['第二次1', '第二次2'])
eb.once('once', test4);
eb.emit('once', '執行一次', 1, 2, 3)
console 輸出結果如下: