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 是一个高效、简洁的组件通信解决方案。合理使用,能让代码更清晰、更灵活。

相关推荐
yivifu18 分钟前
HTML元素的textContent和innerText两个属性的差别
前端·html
Bs_MoneyMagnet29 分钟前
基于springboot+vue的会议室预约管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
天若有情67330 分钟前
开源轻量双语工具|一键批量查询 NPM 包历史下载量,支持按作者批量统计
javascript·npm·github pages·开源工具·netlify·前端开源·npm克隆量
咸鱼老弟42 分钟前
Speculative Decoding(投机采样):大模型"先猜后验",生成速度翻倍
前端·算法·ai编程
Bs_MoneyMagnet1 小时前
基于springboot+vue的茶铺管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
a1117761 小时前
网页版「MATLAB」开源
前端·开源
JianZhen✓1 小时前
解决SPA发版旧版本残留+动态路由打包失效的完整方案(附落地代码)
前端·状态模式
计算机魔术师1 小时前
Dario Amodei 发文呼吁放缓前沿 AI 开发后各方表态汇总
前端
anyup1 小时前
仍然是简单一句话,uView Pro Starter 一键清理 Skill 发布
前端·人工智能·uni-app
福兮说2 小时前
纯前端把图片压缩到指定体积:canvas.toBlob 配合二分查找
前端·javascript·canvas·图片处理