Props/Emit 适合父子直连通信,Pinia 适合跨页面或深层共享状态,事件总线(如 mitt)适合临时性、松耦合的跨组件通知;三者按数据流范围和生命周期逐步升级协作。

Props/Emit 适合父子直连通信,Pinia 适合跨页面或深层共享状态,事件总线(如 mitt)适合临时性、松耦合的跨组件通知。三者不是替代关系,而是按数据流范围和生命周期逐步升级的协作方案。
Props/Emit:明确父子关系下的单向协作
这是 Vue 官方推荐的默认通信方式,强调“父传子数据 + 子触发事件通知父”这一清晰流向。
- 父→子用 props:比如把用户列表、配置项、开关状态等只读数据传给子组件;类型校验和默认值建议显式声明,避免运行时错误
- 子→父用 emits:比如按钮点击后通知父组件刷新、表单提交后回传校验结果;Vue 3 推荐用
defineEmits(['submit', 'cancel'])显式声明,提升可维护性 - 不适用于:兄弟组件间通信、深层嵌套中祖孙传递、或需要持久化/多处监听的状态
Pinia:跨组件、跨路由的统一状态中枢
当多个组件(甚至不同页面)需要读写同一份状态,且该状态有业务含义(如登录态、权限、主题偏好),Pinia 是首选。
- 状态集中管理,支持 TypeScript 类型推导、模块拆分、持久化插件(如
pinia-plugin-persistedstate) - 适合场景:用户登录信息在导航栏、侧边栏、API 请求拦截器中同步使用;系统语言切换后全站响应;购物车数量在 Tab 栏和弹窗中实时一致
- 注意:不要为一次性局部状态(如某个弹窗的打开/关闭)滥用 Pinia,会增加不必要的复杂度
事件总线(mitt):轻量级、临时性的广播通知
mitt 提供了一个极简的发布-订阅机制,不依赖 Vue 实例,体积小(约 200B),适合解耦非强关联组件。
立即学习“前端免费学习笔记(深入)”;
- 典型用法:A 组件触发「刷新列表」事件,B、C、D 等多个无关组件各自监听并执行对应逻辑;或用于跨层级但无 provide/inject 条件的简单通知
- 优势是灵活、低侵入,劣势是缺乏类型提示、调试困难、事件名易冲突、无法追踪数据来源
- 现代项目中建议仅用于过渡方案或工具类交互(如全局快捷键响应、日志埋点触发),长期维护项目优先考虑 Pinia 或组合式 API 封装
选型关键看三点:数据是否跨父子边界、是否需持久或被多处消费、是否涉及副作用或异步协调。理清这三点,通信方式自然就明确了。


















