mitt 专用于瞬时事件广播,不存状态、不管逻辑,适用于 toast 提示、侧边栏同步、跨框架通知等场景;须用单例 event bus,命名带语义层级如 'ui:sidebar:toggled',监听必须配 onunmounted 销毁以防内存泄漏。

用 mitt 处理 Vue 组件间复杂事件传递,关键不是堆功能,而是守住“事件即瞬时通知”这个边界——它不存状态、不管逻辑、只做广播。只要明确这点,再复杂的跨组件联动也能轻量解耦。
什么时候该用 mitt,而不是 Pinia 或 provide/inject
mitt 的定位很清晰:它解决的是“一件事发生了,需要立刻告诉别人”,而不是“这件事的状态要被长期维护”。比如:
- 表单提交成功后,弹出全局 Toast 提示(不需要持久化,只播一次)
- 侧边栏折叠状态变化,多个无关组件需同步收起浮层(状态瞬时同步,不参与业务计算)
- 第三方地图组件触发点击事件,业务组件需响应但无直接引用关系(解耦依赖,避免硬传 ref)
- 微前端场景下,Vue 子应用向 React 子应用发通知(mitt 无框架绑定,天然跨技术栈)
正确创建和复用 event bus 实例
一个项目只需一个全局 emitter,且必须导出为默认对象,避免多实例导致监听失效或内存泄漏:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 在 src/utils/eventBus.js 中统一创建:
import mitt from 'mitt';<br>export default mitt();
- 不要在组件内 new mitt() —— 每个新实例都是独立的,emit 和 on 在不同实例上互不响应
- 如需隔离域(例如测试环境 mock),可用
const testEmitter = mitt(),但生产环境保持单例
事件命名要有语义和层级,别裸奔
随意用 'click' 或 'update' 这类泛名,很快会让项目陷入事件冲突和调试黑洞。推荐用冒号分隔的命名空间:
-
'ui:sidebar:toggled'—— 明确模块(ui)、组件(sidebar)、动作(toggled) -
'auth:token:expired'—— 区分领域(auth)、实体(token)、事件类型(expired) - 避免
'change'这种无上下文名称;也不要用驼峰如'userLoginSuccess',不易扫描和过滤
监听必须配销毁,否则内存泄漏是必然
尤其在动态组件、路由切换、v-if 条件渲染场景下,没 off 的 on 就像没关水龙头:
- 组合式 API 中,始终配合
onUnmounted清理:emitter.on('ui:toast:show', handler);<br>onUnmounted(() => emitter.off('ui:toast:show', handler)); - 如果用
once(只监听一次),mitt 会自动清理,无需手动 off - 切忌在 setup 里直接写
emitter.on(...)而不配卸载逻辑——这是最常见的泄漏源头
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










