事件总线 eventBus 详解

事件总线

提供一个事件总线,给其他的组件或模块以监听和修改数据的权利,它具体做的事情可以有以下几种

  1. 提供监听某个事件的接口
  2. 提供取消监听的接口
  3. 触发事件的接口(可传递数据)
  4. 触发事件后会自动通知监听者

下面介绍一下如何用代码实现事件总线的效果

首先在全局新建一个eventBus.js文件,此文件是与main.js并列等级的,我们希望它导出一个事件总线,其实就是一个对象,里边包含了事件总线的相关配置内容,含有方法接口

/*
* 事件总线
* 具体完成上述的四个功能(其中第四个功能是通过前三个完成的)
* 导出对象,内部包含一些方法,供外部调用
*/
/*
   给一个全局的数组,每次有添加监听事件的时候,就往内部添加一个对象,其属性名是事件名,属性值是一个数组,
   里边是对此事件进行监听的处理函数(因为可能有很多组件或JS模块对该事件进行监听),这里可以使用new Set()
   集合进行自动的去重操作!
   [
   	{'event1': [ handler1, handler2 ]},
   	{'event2': [ handler1 ]},
   ]
*/
const $listeners = [];
export default {
    
    
    // 开启某个事件的监听
    $on(eventName, handler){
    
    
        if(!$listeners[eventName]){
    
    
            $listeners[eventName] = new Set();
        }
        $listeners[eventName].add(handler);
    },
    // 取消某个事件的监听
    $off(eventName, handler){
    
    
        if(!$listeners[eventName]){
    
    
            return;
        }
        $listeners[eventName].delete(handler);
    },
    // 触发某个事件(可以传参),通过剩余参数接受
    $emit(eventName, ...args){
    
    
        if(!listeners[eventName]){
    
    
            return;
        }
        listeners[eventName].forEach((handler)=>{
    
    
            handler(...args);
        });
	}
}

该模块完成之后,我们去到main.js文件中测试,测试代码如下所示

// 测试事件总线接口
import eventBus from "./eventBus";

function handler1(data){
    
    
  console.log("handler1", data);
}

function handler2(data){
    
    
  console.log("handler2", data);
}

eventBus.$on("event1", handler1);
eventBus.$on("event1", handler2);
eventBus.$on("event2", handler1);

window.eventBus = eventBus;
window.handler1 = handler1;
window.handler2 = handler2;

简单解读一下,这段代码相当于在事件总线上添加了两个对象,

第一个是关于事件event1的,里面包含了两个处理函数handler1handler2,存放在一个数组中,并将其赋值给事件event1作为该事件的属性值

第一个是关于事件event2的,里面包含了一个处理函数handler1,存放在一个数组中,并将其赋值给事件event2作为该事件的属性值

最后一部分是为了给全局注册一下事件总线,方便后续在控制台调试

如图所示,运行如下代码,可以看到当使用事件总线抛出一个event1事件的时候,同时运行了两个处理函数,并且将参数数据各自代入到了处理函数中,
在这里插入图片描述

当使用事件总线抛出一个event2事件的时候,运行了handler1处理函数,并且将参数456代入到了处理函数中

在这里插入图片描述

下面测试一下取消事件监听的函数,可以看见,在运行了eventBus.$off("event1", handler1)之后,当事件总线在此抛出event1事件的时候,就会仅仅运行handler2处理函数了,也就是说把handler1在事件event1的处理函数集合中删除掉了,但是对于事件event2的事件处理函数没有影响。

在这里插入图片描述

至此,说明上述事件总线的功能已经完成,并能成功实现我们所期望的效果。

但是这里为什么使用$emit$on等等如此接近于vue的实例成员属性和方法呢,那是因为,在一般的开发当中,其实常常利用一个新的vue实例来完成上述效果,因为一个vue实例内置了上述几个方法。

于是,我们在事件总线模块eventBus.js中便可以如下写

import Vue from "vue";
export default new Vue({
    
    });

就行了,因为vue组件实例对象中就内置了$on,$off,$emit的方法,因此原封不动的就可以直接调用原来的测试代码。

猜你喜欢

转载自blog.csdn.net/facial_123/article/details/126814140