mitt是Vue 3中替代EventBus的轻量级事件总线,专用于兄弟、隔代等无直接关系组件的解耦通信;当prop drilling明显或父子emit不足时适用,需在组件卸载时调用off防止内存泄漏。

Vue 3 中,mitt 是替代 Vue2 EventBus 的轻量级事件总线方案,专为跨组件通信设计,尤其适合兄弟、隔代或无直接关系的组件间解耦通信。
什么时候该用 mitt?
当 props 层层透传(prop drilling)开始明显、父子 emit 不再够用时,就是 mitt 的典型使用时机:
- 兄弟组件需要响应彼此状态(如表单提交后刷新列表)
- 深层嵌套中,祖组件想通知某个孙组件执行动作(比如全局搜索触发侧边栏高亮)
- 多个不相关组件需监听同一类事件(如用户登出后,菜单、头像、缓存模块同步清理)
- 避免把大量中转逻辑堆在父组件里,让父组件只负责结构,不承担通信调度
如何正确配置 mitt 实例?
推荐在 src/utils/eventBus.ts 中统一创建并导出类型安全的实例:
✅ 基础写法(适合快速验证):
立即学习“前端免费学习笔记(深入)”;
import mitt from 'mitt';<br>export const emitter = mitt();
✅ 类型增强写法(推荐用于中大型项目):
分析 Vue 3 Composition API 使用情况——审计响应式模式、可组合函数设计、ref 与 reactive 的选择、计算属性、watcher 使用及组件……
import mitt, { Emitter } from 'mitt';<br><br>type Events = {<br> 'user-login': { id: number; name: string };<br> 'cart-change': { itemId: string; count: number };<br> 'theme-toggle': 'light' | 'dark';<br>}<br><br>export const emitter = mitt<Events>();
这样在 emit 和 on 时都能获得 TypeScript 的参数提示与校验,减少运行时错误。
在组件中发送和接收事件
发送方(比如点击按钮的组件):
import { emitter } from '@/utils/eventBus';<br><br>const handleClick = () => {<br> emitter.emit('user-login', { id: 1001, name: '张三' });<br>};
接收方(比如需要更新用户信息的组件):
import { onMounted, onUnmounted } from 'vue';<br>import { emitter } from '@/utils/eventBus';<br><br>onMounted(() => {<br> emitter.on('user-login', (user) => {<br> console.log('收到登录事件:', user);<br> // 更新本地状态、请求用户数据等<br> });<br>});<br><br>onUnmounted(() => {<br> emitter.off('user-login'); // 必须移除,防内存泄漏<br>});
⚠️ 注意:onUnmounted 中调用 off 是硬性要求,否则组件卸载后监听器仍存在,可能引发重复执行或报错。
mitt 和其他通信方式怎么选?
不必追求“统一”,按场景匹配更高效:
-
父子传值 → 优先用
defineProps+defineEmits(官方、类型强、性能好) -
祖孙透传少量属性 → 用
useAttrs或provide/inject(后者更适合深层固定依赖) - 多组件共享状态+持久化 → 上 Pinia(比 mitt 更适合管理复杂业务状态)
- 临时广播、解耦通知、非状态类交互 → mitt 正是为此而生,不存状态、不管理副作用,只做“喊一嗓子”

















