Vue3中事件总线的具体使用

Miette ·
更新时间:2024-09-20
· 1309 次阅读

目录

导读

事件总线的本质

构建一个EventEmitter

config.globalProperties方法

provide/inject

结束语

导读

在Vue2中,我们遇到复杂的组件通信时,经常采用事件总线的方式来通信。其具体的思路就是实例化一个空白的Vue,并通过其提供的$on$once$emit方法来进行通信。而在Vue3中,上述三个API已经被移除了,那么我们又如何使用事件总线呢?

事件总线的本质

Vue2中的$on$once$emit本质上就是其内部实现了一个EventEmitter(事件派发器),每一个事件都和若干回调相对应,只要事件被触发,那么就将执行此事件所有对应的回调。同时,在JavaScript中,该思想被广泛地使用,尤其在Node.js的事件机制中,就是创建了一个EventEmitter实例,具体请自行查阅相关资料。因此,我们只需要实现一个简单的EventEmitter,并全局传递到每一个组件中,就可以实现一个事件总线了。而全局传递,我们可以使用config.globalProperties绑定到每一个组件,也可以在根组件(main)中,通过provide提供总线,需要使用的组件使用inject注入。下面就让我们来实现一下吧。

构建一个EventEmitter

由于我们可能会有多条总线,我们还是把EventEmitter写成类的方式,每一条总线都将是一个EventEmitter实例。以下是EventEmitter的简单实现,其只实现了ononceemit三个API。

class EventEmitter{ constructor(){ this.callbacks={}; } on(envetName,callback){ if(!Array.isArray(this.callbacks[envetName])){ this.callbacks[envetName]=[]; } this.callbacks[envetName].push(callback); } emit(eventName,...args){ if(Array.isArray(this.callbacks[eventName])){ this.callbacks[eventName].forEach(callback=>callback(...args)); } } off(eventName,callback){ if(!Array.isArray(this.callbacks[eventName])){ return } if(callback){ this.callbacks[eventName].forEach(cb=>{ if(callback===cb){ this.callbacks[eventName].splice(this.callbacks[eventName].indexOf(callback),1); } }); } else{ this.callbacks[eventName]=[]; } } once(eventName,callback){ const that=this; const fn=function(){ callback.apply(that,[...arguments]); that.off(eventName,fn); } that.on(eventName,fn); } }

具体的代码基本上还是很好理解的,就不在本文解释了,具体请自行查阅相关的资料。

将EventEmitter实例化并全局引入

上文已经说了有两种引入EventEmitter的方法,这里简单地给个参考实例吧。

config.globalProperties方法

在main.js中

import { createApp } from 'vue' import './style.css' import App from './App.vue' const app=createApp(App); app.config.globalProperties.$event=new EventEmitter(); app.mount('#app')

在组件中:

//Comp1 <script setup> import {getCurrentInstance} from "vue" const vm=getCurrentInstance(); vm.proxy.$event.on('test',()=>{ console.log('test event emit!') }) </script> //Comp2 <script setup> import {getCurrentInstance} from "vue" const vm=getCurrentInstance(); vm.proxy.$event.emit('test',"a","b") </script>

但这种方法不太优雅,不方便定义多条总线,建议使用下述的方法。

provide/inject

在main.js中

provide("eventBus1",new EventEmitter()); provide("eventBus2",new EventEmitter());

在组件中

//Comp1 <script setup> import {inject} from "vue"; const bus1=inject("eventBus1") bus1.on("bus1-on-event",()=>{ console.log('eventBus1 on event emit!') }) </script> //Comp2 <script setup> import {inject} from "vue"; const bus1=inject("eventBus1") const bus2=inject("eventBus2") bus2.on("bus2-on-event",()=>{ console.log('eventBus2 on event emit!') }) bus1.emit("bus1-on-event") </script> //Comp3 <script setup> import {inject} from "vue"; const bus2=inject("eventBus2") bus2.emit("bus2-on-event") </script>

此方法中,使用inject也比使用getCurrentInstance.proxy更优雅一些,且不使用就不必使用inject注入。

结束语

到此这篇关于Vue3中事件总线的具体使用的文章就介绍到这了,更多相关Vue3 事件总线内容请搜索软件开发网以前的文章或继续浏览下面的相关文章希望大家以后多多支持软件开发网!



VUE 事件

需要 登录 后方可回复, 如果你还没有账号请 注册新账号