文章目录
-
- 一、先创建事件总线实例
- 二、逐行讲解用法
-
- [1. Bus.on(eventName, callback):监听事件](#1. Bus.on(eventName, callback):监听事件)
- [2. Bus.emit(eventName, ...args):触发事件](#2. Bus.emit(eventName, ...args):触发事件)
- [3. Bus.off(eventName, callback):取消监听](#3. Bus.off(eventName, callback):取消监听)
- 三、完整实战示例(两个组件通信)
-
- [组件 A(发送方:emit)](#组件 A(发送方:emit))
- [组件 B(接收方:on + off)](#组件 B(接收方:on + off))
- 四、高频注意事项(必看)
- 五、极简原生JS版(不依赖框架)
- 六、知识总结

Bus.on、Bus.emit、Bus.off 这三个是事件总线(EventBus) 的核心方法,专门用来解决跨组件/跨页面/跨模块通信(比如兄弟组件传值、无关联模块互相通知),是前端(Vue/React/小程序等)最常用的简易通信方案。
先记核心口诀:
- Bus.on :监听/订阅事件(等着别人发通知)
- Bus.emit :触发/发布事件(给别人发通知)
- Bus.off :取消监听(不再接收通知,防止内存泄漏)
一、先创建事件总线实例
所有用法都基于一个全局唯一的 Bus 实例,以 Vue 为例(原生JS/小程序/React 用法完全一致):
javascript
// utils/bus.js (单独创建一个文件)
import Vue from 'vue'
// 导出一个空的 Vue 实例作为事件总线
export default new Vue()
二、逐行讲解用法
1. Bus.on(eventName, callback):监听事件
作用:监听一个自定义事件,别人触发这个事件时,你这里的回调函数就会执行。
参数:
eventName:事件名(字符串,自定义,如'updateData')callback:触发时执行的函数
用法示例:
javascript
import Bus from '@/utils/bus'
// 监听 "message" 事件
Bus.on('message', (data) => {
// data 就是 emit 传递过来的数据
console.log('收到消息:', data)
})
2. Bus.emit(eventName, ...args):触发事件
作用 :主动发布/触发一个事件,所有监听了这个事件的地方都会收到通知。
参数:
eventName:和on对应的事件名...args:要传递的数据(可以传多个参数)
用法示例:
javascript
import Bus from '@/utils/bus'
// 触发 "message" 事件,并传递数据
Bus.emit('message', { name: '小明', text: '你好' })
👉 执行后 :上面 Bus.on('message') 的回调会立刻执行,并拿到传递的对象。
3. Bus.off(eventName, callback):取消监听
作用 :销毁事件监听,必须用 ,否则会造成重复触发、内存泄漏。
两种常用用法:
- 取消指定事件+指定回调(最标准)
- 取消该事件所有监听
javascript
import Bus from '@/utils/bus'
// 1. 先定义回调函数(必须用同一个函数引用,off 才能精准取消)
const handleMessage = (data) => { console.log(data) }
// 监听
Bus.on('message', handleMessage)
// 2. 取消指定监听(推荐)
Bus.off('message', handleMessage)
// 3. 取消该事件的所有监听
Bus.off('message')
三、完整实战示例(两个组件通信)
组件 A(发送方:emit)
vue
<template>
<button @click="sendMsg">发送消息给B组件</button>
</template>
<script>
import Bus from '@/utils/bus'
export default {
methods: {
sendMsg() {
// 触发事件,传数据
Bus.emit('toB', '来自A组件的消息')
}
}
}
</script>
组件 B(接收方:on + off)
vue
<script>
import Bus from '@/utils/bus'
export default {
created() {
// 1. 监听事件
Bus.on('toB', this.getMsg)
},
methods: {
getMsg(data) {
console.log('B组件收到:', data)
}
},
beforeDestroy() {
// 2. 组件销毁时取消监听!!!关键
Bus.off('toB', this.getMsg)
}
}
</script>
四、高频注意事项(必看)
- 事件名必须完全一致(大小写敏感)
- 回调函数必须是同一个引用
不要写匿名函数:Bus.on('msg', ()=>{}),否则 Bus.off 无法取消,会造成重复触发! - 必须在组件销毁时 off
页面切换/组件销毁时一定要取消监听,否则事件会越来越多,导致卡顿、重复执行。 - 可以一对多:一个 emit,多个 on 都能收到。
五、极简原生JS版(不依赖框架)
如果不用 Vue,用原生 JS 手写简易 Bus,逻辑完全一样:
javascript
class Bus {
constructor() {
this.events = {} // 存储事件
}
// 监听
on(name, fn) {
this.events[name] = this.events[name] || []
this.events[name].push(fn)
}
// 触发
emit(name, ...args) {
this.events[name]?.forEach(fn => fn(...args))
}
// 取消
off(name, fn) {
if(!this.events[name]) return
this.events[name] = this.events[name].filter(f => f !== fn)
}
}
// 导出实例
export default new Bus()
✅ 用法和上面完全相同。
六、知识总结
- Bus.on:监听事件,准备接收数据
- Bus.emit:触发事件,发送数据
- Bus.off:取消监听,防止bug
- 固定流程:
on 监听 → emit 触发 → off 销毁 - 核心用途:无关联模块之间通信