ES6實現EventEmitter類

自定義事件類主要有四個方法,分別爲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)
複製代碼

這裏是簡易自定義事件類的實現,你們可根據自我需求進行完善。

相關文章
相關標籤/搜索