EventTarget:自定义事件

216 阅读2分钟

打好基础,查漏补缺

基础是重中之重

需求产生

某天,经理给我一个需求,在a逻辑之后会执行b逻辑。于是我写了 fnc1方法,将b逻辑写在其中,完美无缺。

function fnc1 (){
    console.log('很多逻辑b')
}

过几天,这个需求发生变动,在a逻辑之后,不仅要执行b逻辑,还要执行c逻辑.如果和下面的方法一样,就会造成代码耦合,越来越臃肿,维护性也很差。

function fnc1 (){
    console.log('很多逻辑b')
    console.log('很多逻辑c')
}

于是我自然有另外一个想法,写一个函数fnc2,将c逻辑全部写在里面。在执行完a逻辑之后调用fnc1,fnc2。但我总感觉有些不足,但我还是去做其他事情了。

function fnc1 (){
    console.log('很多逻辑a')
}
function fnc2 (){
    console.log('很多逻辑b')
}

fnc1()
fnc2()

这边我遇到了新需求,需要给某个按钮绑定两个事件。我心中一想,这还不简单。

function fnc1 (){
    console.log('很多逻辑a')
}
function fnc2 (){
    console.log('很多逻辑b')
}

document.getElementById('btn').addEventListener('click',fn1,false)
document.getElementById('btn').addEventListener('click',fn2,false)

当写完这行代码,我突然想到之前那个需求,和这不是一模一样?我能不能写一个自定义事件,将我的逻辑全部绑定在a逻辑(事件)之上?

代码


// 1. 首先,我需要有个地方将我的逻辑存储起来

let handler = {
    aEvent:[fnc1,fnc2] // a逻辑之上绑定了我需要执行的所有逻辑
}

// 2、有了存储的地方,我就需要一个方法能将之后的逻辑全部绑定到对应事件中

addEvent(event,fn){
    if (handler[event] == undefined){
        handler[event] = []
    } else {
        handler[event].push(fn)
    }
}

// 3、既然能绑定事件,那么自然也要能移除事件

removeEvent(event,fn){
    if (handler[event] == undefined){
        return
    } else {
    for (let i = 0; i < handler[event].length; i++){
        if (handler[event][i] == fn){
            handler[event][i].splice(i,1)
            return 
        }
    }
    }
}

// 4.最后,我们需要去触发这个事件执行

trigger(event){
    if (!(event in handler)){
        return 
    } else {
          for (let i = 0; i < handler[event].length; i++){
             handler[event][i]()
        }
    }
}

这就基本完成逻辑梳理。

下面是完整版

class myEvent{

    constructor(event,fn){
        this.event = event
        this.fn = fn
        this.handler = {}
    }
    
    addEvent(event,fn){
        if (this.handler [event] == undefined){
            this.handler [event] = []
        } else {
            this.handler [event].push(fn)
        }
    }
    
    removeEvent(event,fn){
        if (this.handler [event] == undefined){
            return
        } else {
        for (let i = 0; i < this.handler [event].length; i++){
            if (this.handler [event][i] == fn){
                this.handler [event][i].splice(i,1)
                return 
            }
        }
        }
    }
    
    trigger(event){
        if (!(event in this.handler )){
            return 
        } else {
              for (let i = 0; i < this.handler [event].length; i++){
                 this.handler [event][i]()
            }
        }
    }
}
let newEvent = new myEvent()
newEvent.addEvent('myEvent',fn1)
newEvent.addEvent('myEvent',fn2)
newEvent.trigger('myEvent')

##系统内部的EventTarget 与我们的写法类似

let newEvent = new EventTarget('myEvent')
newEvent.addEventListener('myEvent',fn1)
newEvent.dispatchEvent('myEvent')