事件总线 eventBus 详解

  • Post author:
  • Post category:其他




事件总线

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

  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

的,里面包含了两个处理函数

handler1



handler2

,存放在一个数组中,并将其赋值给事件

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

的方法,因此原封不动的就可以直接调用原来的测试代码。



版权声明:本文为facial_123原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。