在 Vue 3 的开发中,随着 Options API 向 Composition API 的演进,传统的 $emit / $on(即 Vue.prototype.$bus)方式已被移除。对于非父子关系的组件通信(如兄弟组件、跨层级组件),开发者需要一种轻量、灵活的替代方案。此时,mitt 这个微型事件发布/订阅库便成为了一个优秀的选择。
一、mitt 是什么?
mitt 是一个仅有 ~200 字节的微型事件发射器(Event Emitter),支持 on、off、emit 等基本操作。它不依赖任何框架,但特别适合用于 Vue、React 等现代前端框架中作为全局事件总线(Event Bus)。
相比于 Vuex 或 Pinia,mitt 更轻量;相比于 provide/inject,它更适合松耦合的跨组件通信。
二、项目结构简析
我们关注两个核心文件:
eventbus.js:mitt 实例的创建与导出index.vue:联系页面组件,包含三个 Tab(联系总部、办公地址、在线留言),点击 Tab 时需滚动到对应内容区域
1. 创建全局事件总线(eventbus.js)
// utils/eventbus.js
import mitt from 'mitt';
const emitter = mitt();
export default emitter;
这行代码创建了一个全局唯一的 emitter 实例,并将其导出供其他模块使用。
2. 在组件中使用 mitt(index.vue)
(1)导入并使用
import emitter from "@/utils/eventbus.js"
(2)触发事件
当用户点击 Tab 时,不仅切换当前激活项,还通过 emitter.emit 发送一个 scroll 事件,并携带目标 Tab 编号:
const handleChose = (val) => {
currentTab.value = val;
emitter.emit("scroll", currentTab.value); // 👈 关键:广播滚动指令
}
(3)监听事件(虽未在本文件体现,但通常在父组件或布局组件中)
虽然 index.vue 本身没有监听 scroll 事件,但根据命名和逻辑可推断:在页面的父级或 App.vue 中,必然存在对 scroll 事件的监听 ,用于执行 scrollIntoView 或 window.scrollTo 操作,实现平滑滚动到对应区块(如 .headquartersRef, .addressRef 等)。
例如,在父组件中可能有如下逻辑:
// 假设在 App.vue 或 Layout.vue 中
import emitter from '@/utils/eventbus.js'
onMounted(() => {
emitter.on('scroll', (tabIndex) => {
const refMap = { 1: headquartersRef, 2: addressRef, 3: messageRef };
const targetRef = refMap[tabIndex];
if (targetRef?.value) {
targetRef.value.scrollIntoView({ behavior: 'smooth' });
}
});
});
onUnmounted(() => {
emitter.off('scroll'); // 避免内存泄漏
});
💡 注意:虽然当前
index.vue文件未展示监听端,但emitter.emit("scroll", ...)的存在强烈暗示了这种跨组件通信模式。
三、mitt 的核心优势
- 轻量无依赖:仅 200B,不影响打包体积。
- 解耦性强:发送方与接收方无需知道彼此的存在,只需约定事件名。
- 适用于任意组件关系:父子、兄弟、跨多层均可。
- TypeScript 友好:可通过泛型定义事件类型,提升开发体验。
四、使用注意事项
-
及时销毁监听器
在组件卸载时(
onUnmounted)务必调用emitter.off(eventName, handler),否则可能导致内存泄漏或重复触发。 -
避免滥用
mitt 适合少量、关键的全局事件。若状态复杂,仍应优先考虑 Pinia/Vuex。
-
事件命名规范
建议使用常量或枚举管理事件名,避免魔法字符串:
// eventTypes.js export const SCROLL_TO_SECTION = 'SCROLL_TO_SECTION';
五、总结
在中梓科技的联系页面中,mitt 被巧妙地用于实现 Tab 切换与页面滚动的联动。这种模式将 UI 交互逻辑(点击 Tab)与 DOM 操作逻辑(滚动到区块)分离,提升了代码的可维护性与可读性。
对于中小型 Vue 3 项目,mitt 是一个高效、简洁的组件通信解决方案。合理使用,能让代码更清晰、更灵活。