Vue 3 中使用 mitt 实现组件间通信的实践与解析

在 Vue 3 的开发中,随着 Options API 向 Composition API 的演进,传统的 $emit / $on(即 Vue.prototype.$bus)方式已被移除。对于非父子关系的组件通信(如兄弟组件、跨层级组件),开发者需要一种轻量、灵活的替代方案。此时,mitt 这个微型事件发布/订阅库便成为了一个优秀的选择。


一、mitt 是什么?

mitt 是一个仅有 ~200 字节的微型事件发射器(Event Emitter),支持 onoffemit 等基本操作。它不依赖任何框架,但特别适合用于 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 事件的监听 ,用于执行 scrollIntoViewwindow.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 的核心优势

  1. 轻量无依赖:仅 200B,不影响打包体积。
  2. 解耦性强:发送方与接收方无需知道彼此的存在,只需约定事件名。
  3. 适用于任意组件关系:父子、兄弟、跨多层均可。
  4. TypeScript 友好:可通过泛型定义事件类型,提升开发体验。

四、使用注意事项

  1. 及时销毁监听器

    在组件卸载时(onUnmounted)务必调用 emitter.off(eventName, handler),否则可能导致内存泄漏或重复触发。

  2. 避免滥用

    mitt 适合少量、关键的全局事件。若状态复杂,仍应优先考虑 Pinia/Vuex。

  3. 事件命名规范

    建议使用常量或枚举管理事件名,避免魔法字符串:

    复制代码
    // eventTypes.js
    export const SCROLL_TO_SECTION = 'SCROLL_TO_SECTION';

五、总结

在中梓科技的联系页面中,mitt 被巧妙地用于实现 Tab 切换与页面滚动的联动。这种模式将 UI 交互逻辑(点击 Tab)与 DOM 操作逻辑(滚动到区块)分离,提升了代码的可维护性与可读性。

对于中小型 Vue 3 项目,mitt 是一个高效、简洁的组件通信解决方案。合理使用,能让代码更清晰、更灵活。

相关推荐
呃m2 小时前
更好地使用Google Chrome
前端·chrome
巧克力芋泥包2 小时前
Vue3 详情页跨页循环(上一条,下一条)导航功能实现
前端·javascript·vue.js
摘星编程2 小时前
React Native + OpenHarmony:BottomSheet联动效果实现
javascript·react native·react.js
前端之虎陈随易2 小时前
前端通用插件开发工具unplugin v3.0.0发布
前端·typescript
Ashley_Amanda2 小时前
SAP调用Web Service全流程详解
java·前端·数据库
Dreamy smile2 小时前
css :nth-child() 完全用法指南
前端·css
Southern Wind2 小时前
从零开始封装一个优雅的图片上传组件 - 二次改装 Layui-Upload 的教程(附完整封装代码)
前端·javascript·html·layui·css3
小白菜学前端2 小时前
Vue3 + TS 解决 ESLint 与 Prettier 格式化冲突
前端·javascript·vue.js