目录
前言
在 Vue 3 中,默认情况下是没有内置的 EventBus,也就是说,Vue 3 没有像 Vue 2 那样的 $on()
和 $emit()
的全局事件系统。
这是因为在 Vue 3 中,官方推荐使用 Composition API 以及更灵活的函数式组件,同时提倡使用更明确的通信方式。比如props
、emits
、provide
/inject
、pinia。
不过在一些小项目中,我们仍然希望可以使用eventBus而不用pinia进行全局的管理。这个时候,Vue3里使用最广来实现eventBus的方法就是第三方库mitt。
一、mitt介绍及使用
Vue 3 中的 mitt 是一个简单而强大的事件总线库,用于在组件之间进行事件的发布和订阅。它提供了一种简洁的方式来实现组件之间的通信,而无需借助 Pinia 或其他状态管理库。
1. 安装
npm install mitt
# 或者
yarn add mitt
# 或者
pnpm install mitt
2. 创建bus.ts
src/utils/bus.ts
import mitt from 'mitt'
type Events = {
sendMsg: string
sendNum: number
}
const bus = mitt<Events>()
export default bus
3. 使用
mitt
暴露了三个api :on
、off
、emit,
以及all
实例。
// 发布一个事件
bus.emit('foo', { a: 'b' })
// 订阅一个具体的事件
bus.on('foo', (e) => console.log('foo', e))
// 订阅所有事件
bus.on('*', (type, e) => console.log(type, e))
// 取消订阅同名事件
bus.off('foo') // unlisten
// 取消所有事件
bus.all.clear()
4. 案例
TestAll.vue:
<template>
<h1>mitt</h1>
<hr />
<test-mitt1 />
<hr />
<test-mitt2 />
</template>
<script setup></script>
TestMitt1.vue:
<template>
<h1>发射</h1>
<div>
<button @click="send">Click me!</button>
</div>
</template>
<script setup lang="ts">
import bus from '@/utils/bus'
function send() {
bus.emit('sendMsg', 'hello')
}
</script>
TestMitt2.vue:
<template>
<h1>接收</h1>
<div>
<p>{{ msg }}</p>
</div>
</template>
<script setup lang="ts">
import bus from '@/utils/bus'
const msg = ref('未接收到')
bus.on('sendMsg', (data) => {
msg.value = data
})
</script>
二、mitt优势及注意事项
1. 优势
-
API 简洁易用:mitt 提供了一个简单且直观的 API,使得事件的发布和订阅变得非常容易。你只需导入 mitt 库并创建一个事件总线对象,然后通过 emit() 发布事件,通过 on() 订阅事件。相比之下,Vue 2 的 EventBus 需要通过 $emit() 发布事件,而通过 $on() 订阅事件。
-
无需依赖 Vue 实例:mitt 是一个独立的事件总线库,不需要依赖于 Vue 实例。这意味着你可以在任何地方使用 mitt 来进行事件的管理,而不仅限于 Vue 组件之间的通信。与之相反,Vue 2 的 EventBus 是以全局 Vue 实例为基础的,只能在 Vue 组件中使用。
-
更好的模块化支持:由于 mitt 不依赖于 Vue 实例,它更适用于模块化开发环境,可以与其他框架或库结合使用。这使得在复杂的应用程序中,不同模块之间的通信更加灵活和简单。
-
更好的性能:mitt 在性能方面表现出色。它使用了快速且高效的内存管理技巧,能够更好地处理大量的事件并保持高性能。与 Vue 2 的 EventBus 相比,mitt 在事件的传递和处理上更加高效。
2. 注意事项
- 当使用 mitt 进行组件通信时,需要确保安装了 mitt 库,并且在需要通信的组件中都引入了 mitt
- 在多个地方引入 mitt 时,要确保使用的是同一个事件总线对象,以便实现正确的事件发布和订阅。
- 注意在适当的时机取消事件的订阅,防止内存泄漏。
- 尽量避免过度使用事件总线,以免导致代码复杂性增加。若组件之间的通信较为复杂,可考虑使用 Pnia 或其他状态管理库来管理组件间的共享状态。