自定義事件類主要有四個方法,分別爲on、once、off、emit。這裏咱們採用class語法來實現:數組
class結構:app
class EventEmitter {
constructor () {
this.events = {}
}
on (event, cb) {
return this
}
off (event, cb) {
return this
},
once (event, cb) {
return this
},
emit (event, ...args) {
return this
}
}
複製代碼
events
是一個對象,用來存儲事件名以及對應的回調函數;return this
返回該實例,能夠鏈式調用。函數
on的實現:測試
on (event, cb) {
if (!this.events[event]) {
this.events[event] = []
}
this.events[event].push(cb)
return this
}
複製代碼
首先判斷該event是否存在,若不存在則初始化爲空數組(由於一個事件能夠屢次註冊,可能會對應多個方法,因此這裏使用數組存儲函數),而後將函數添加進去;若event存在則直接添加到該事件的函數列表中。ui
若是對可讀性要求不高,可寫成:this
on (event, cb) {
(this.events[event] || this.events[event] = []).push(cb)
return this
}
複製代碼
off的實現:spa
off (event, cb) {
if (!cb) {
this.events[event] = null
} else {
this.events[event].some((fn, i) => {
if (cb === fn) {
this.events[event].splice(i, 1)
return true
}
})
}
return this
}
複製代碼
首先判斷是否有cb參數,即具體的函數,若是沒有則將整個event清空,若是有則將對應的fn清除,這裏只清除第一個,若是須要清除所有能夠使用forEach,不終止循環。code
once的實現:對象
once (event, cb) {
const func = (...args) => {
this.off(event, func)
cb.apply(this, args)
}
this.on(event, func)
return this
}
複製代碼
在內部定義一個函數,該函數只會執行一次,執行完後當即清除,即調用off方法,而後調用cb,即該事件註冊時對應的方法。事件
emit的實現:
emit (event, ...args) {
const cbs = this.events[event]
if (!cbs) {
throw new Error(`${event} event is not registered.`)
}
cbs.forEach(cb => cb.apply(this, args))
return this
}
複製代碼
首先判斷是否註冊該事件,未註冊則報錯,若是註冊了則執行該函數
測試
const add = (a, b) => console.log(a + b)
const log = (...args) => console.log(...args)
const event = new EventEmitter()
event.on('add', add)
event.on('log', log)
event.emit('add', 1, 2) // 3
event.emit('log', 'hi~') // 'hi~'
event.off('add')
event.emit('add', 1, 2) // Error: add event is not registered.
event.once('once', add)
event.emit('once', 1, 2) // 3
event.emit('once', 1, 2)
event.emit('once', 1, 2)
複製代碼
這裏是簡易自定義事件類的實現,你們可根據自我需求進行完善。