Vue3项目中使用EventBus

前言

在 Vue3 中,由于 $on$off$emit 等实例方法被移除,官方不再推荐使用传统的 EventBus 模式。

mitt 是一个轻量级的事件发射器库,体积小(约 200 字节)且支持全部事件的监听 / 触发,是 Vue3 中实现 EventBus 的主流方案。

编译环境下使用

安装 mitt

1
2
3
npm install mitt --save
# 或
yarn add mitt

创建全局事件总线实例

src/utils/eventBus.js 中创建:

运行

1
2
3
4
import mitt from 'mitt'
// 创建事件总线实例
const eventBus = mitt()
export default eventBus

使用事件总线

发送事件(A 组件)

1
2
3
4
5
6
7
<script setup>
import eventBus from '@/utils/eventBus'
// 触发事件(可传递参数)
const handleClick = () => {
eventBus.emit('send-message', 'Hello from A组件')
}
</script>

监听事件(B 组件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script setup>
import eventBus from '@/utils/eventBus'
import { onMounted, onUnmounted } from 'vue'

onMounted(() => {
// 监听事件(回调函数接收参数)
eventBus.on('send-message', (msg) => {
console.log('收到消息:', msg) // 输出:收到消息:Hello from A组件
})
})

onUnmounted(() => {
// 移除事件监听(避免内存泄漏)
eventBus.off('send-message')
})
</script>

监听所有事件

1
2
3
eventBus.on('*', (type, msg) => {
console.log('事件类型:', type, '参数:', msg)
})

清除所有事件

1
eventBus.all.clear() // 适用于需要重置事件总线的场景

网页中使用

在一些事件注入的场景中,我们要在非编译的页面中监听事件,就要使用这种方式。

引用

在静态 HTML 页面的 <head><body> 中,通过 CDN 引入 mitt 库。

1
2
<!-- 使用 unpkg CDN -->
<script src="https://unpkg.com/mitt@3/dist/mitt.umd.js"></script>

引入后,全局会暴露一个 mitt 函数,用于创建事件总线实例。

创建事件总线实例

在脚本中调用 mitt() 创建全局事件总线:

1
2
3
4
<script>
// 创建事件总线实例
window.eventBus = mitt();
</script>

使用事件总线

可以在页面的任何脚本中使用 eventBus 进行事件通信。

例如:

1
2
3
4
5
6
7
8
9
10
<script>
window.eventBus = window.mitt()
window.eventBus.on('message', (data) => {
console.info('收到消息:', data)
})

setTimeout(() => {
window.eventBus.emit('message', '你好')
}, 2000)
</script>

完整示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>静态页面使用 mitt</title>
<!-- 引入 mitt -->
<script src="https://unpkg.com/mitt@3/dist/mitt.umd.js"></script>
</head>
<body>
<button id="btn">触发事件</button>
<div id="result"></div>

<script>
// 创建事件总线实例
window.eventBus = mitt();

// 监听事件(例如:监听 'message' 事件)
window.eventBus.on('message', (data) => {
document.getElementById('result').textContent = `收到消息:${data}`;
});

// 给按钮绑定点击事件,触发 'message' 事件
document.getElementById('btn').addEventListener('click', () => {
window.eventBus.emit('message', 'Hello from 按钮点击!');
});

// 示例:监听所有事件
window.eventBus.on('*', (type, data) => {
console.log(`事件类型:${type},数据:${data}`);
});

// 示例:移除事件监听(可选)
// 先定义一个回调函数
const handleRemove = (data) => {
console.log('这是一个可移除的监听:', data);
};
// 监听事件
window.eventBus.on('removeTest', handleRemove);
// 移除监听(需要传入原回调函数)
setTimeout(() => {
window.eventBus.off('removeTest', handleRemove);
console.log('已移除 removeTest 事件的监听');
}, 5000);
</script>
</body>
</html>