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)
复制代码

这里是简易自定义事件类的实现,你们可根据自我需求进行完善。

相关文章
相关标签/搜索