手写发布订阅者模式

116 阅读1分钟
实现思路

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)