实现思路
1. 一个Observer类
类的构造函数包含一个消息队列,对象的形式
2. $on方法
接收一个事件名,一个回调函数
observer.$on('事件',fn)
该方法执行时向消息队列中添加属性名为事件名,属性值为由回调函数组成的数组。
//消息队列中保存的内容
message = {
'事件名1':[handler1,handler2,handler3...],
'事件名2':[handler1,handler2,handler3...],
...
}
3. $emit方法
接收一个或多个参数,第一个参数为事件名,其余参数要传入回调函数中的参数
observer.$emit('事件名',args)
该方法执行时会将参数传入事件名对应的回调函数中,并且执行事件名对应的回调函数。
4. $off方法
接收一个或两个参数,第一个参数为事件名,第二个参数为该事件中需要取消的回调函数名。
observer.$off('事件名')
observer.$off('事件名',fn)
该方法执行时,如果只有事件名,则直接从消息队列中取消整个事件,如果要删除事件中某个回调函数,就过滤掉对应的回调函数。
代码实现
class Observer{
constructor(){
//一个消息队列,对象
this.message = {}
}
//on方法接收一个事件名,一个回调函数,并且往消息队列中添加属性名为事件名,属性值为由回调函数组成的数组
$on(type,fn){
//如果消息队列中有type事件名,就向里面添加事件
//如果消息队列中没有事件名,就初始化一个数组
if(!this.message[type]){
this.message[type] = [fn]
}else{
this.message[type].push(fn);
}
}
$off(type,fn){
//如果没有type,return
if(!this.message[type])return
//如果有type,没有fn,直接删除整个事件
if(!fn){
this.message[type] = undefined;
return
}
//如果有type,有fn,就只删除一个fn
this.message[type] = this.message[type].filter((item) =>item !== fn)
}
$emit(type,...args){
//遍历消息队列,然后执行每一项
//判断有没有
if(!this.message[type])return
this.message[type].forEach(element => {
element(...args);
});
}
}
//实例化一个观察者
let person = new Observer();
//向这个观察者委托事件
person.$on('寻找hsh',handlerB);
person.$on('叫hsh来',handlerA);
//向这个观察者移除事件,两种方式,一种是删除整个事件,第二种是删除其中一个回调
// person.$off('叫hsh来');
// person.$off('叫hsh来',handlerA)
//$emit('事件') 执行消息队列中的事件
person.$emit('寻找hsh','咦?')
person.$emit('寻找hsh','咦咦咦?')
person.$emit('叫hsh来','啊!')
function handlerA(a){
console.log(a+'hsh来啦')
}
function handlerB(b){
console.log(b+'hsh呢')
}
console.log(person)