首先大家先思考一个问题,一个对象,里边是(你需要的事件名称,和对应的方法函数队列)像下面这样,
let events = {
myclick: [fn1,fn2],
myfous: [fn3,fn4,fn5,...]
...
}
events[eventName].forEach(fn => fn() )
就是这么简单哈哈哈。现在你来实现这个类,可以new出这这个对象吗?new不出来的同学继续看下边的例子。
举一个dom事件的例子,看下面dom对象为啥就可以直接订阅 click和mousedown事件呢,说明dom类里面是不是已经定义好了呢。
function todosomething1(){}
function todosomething2(){}
div1.addEventListener('click',todosomething1)
div2.addEventListener('click',todosomething2)
div3.addEventListener('mousedown',todo)
所以我们就可以直接emit了,执行对应的事件,里边的回调函数todosomething1,就是我们要执行的东西。还可以传参数过去,是不是很简单?vue里边的$emit也一样的原理。
发布订阅其实就是自定义事件,下边实现一个类,on方法为添加自定义事件,emit为执行自定义事件,off为删除自定义事件。
下边是代码实现,欢迎大家留言讨论啊。
class EventHub {
constructor(){
this.events = {} //保存事件名称
}
//订阅
on(eventName, callback){ //数组保存事件执行的回调
this.events[eventName] = this.events[eventName] || []
this.events[eventName].push(callback)
}
//发布
emit(eventName, data){
(this.events[eventName] || []).forEach(callback=>{
callback(data)
})
}
//取消
off(eventName, callback){
if (this.events[eventName]) {
this.events[eventName] = this.events[eventName].filter(fn=>{
return fn !=callback
})
}
}
once(eventName, callback){
let fn = ()=>{
callback()
this.off(eventName,fn)
}
this.on(eventName,fn)
}
}
let em = new EventHub()
function doconsole1(data){
console.log(data+'1')
}
function doconsole2(data){
console.log(data+'2')
}
em.on('myconsole',doconsole1)//订阅, 定义
em.on('myconsole',doconsole2)//订阅, 定义
em.emit('myconsole','测试的')//发布。执行
em.off('myconsole', doconsole1)
em.emit('myconsole','测试的')//发布。执行
所以我们自定了一个myconsole事件。所以执行可输出
测试的1
测试的2 =》第一个执行emit都执行了。
测试的2 =》off 删除了第一个,所以只剩测试2了。