首页 > 基础资料 博客日记

Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看

2026-04-16 15:30:02基础资料围观1

本篇文章分享Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看,对你有帮助的话记得收藏一下,看极客资料网收获更多编程知识

是不是每次遇到跨层级组件传值,就感觉代码像一团乱麻?明明用的是Vue 3,却还在用Vue 2的思维写一堆层层转发的 propsemits

之前重构一个后台管理项目,一个表单深埋在三级路由下,要把数据传给顶栏的用户头像更新状态。看着那个 defineEmits 链条像击鼓传花一样传了三四层,我直接给自己整笑了。🎯 这玩意儿维护起来,简直是噩梦。

今天咱不聊那些虚无缥缈的源码解析,就踏踏实实地、像唠嗑一样,把这五种 Vue 3 组件通信方式捋一遍。

我的目标只有一个:让你看完之后,能根据不同的场景,像掏工具包一样,“唰”地拿出最趁手的那把螺丝刀。


🎯 核心摘要:这篇文章能帮你省下多少头发?

这不仅仅是一份API清单。我会把这五种通信方式比作家里的水管系统,你马上就能明白什么时候该用直通管,什么时候该打个“眼儿”直连楼下。

更重要的是,我会把我踩过的坑——比如用 mitt 忘了解绑导致页面崩了的血泪史——都给你标出来。

📋 主要内容脉络(看一眼就知道该往哪看)

👉 父子直连: PropsEmits (最基础,别嫌烦)

👉 隔代传功: provide/inject (跨级神器,但有坑)

👉 双向奔赴: v-model (Vue 3 的语法糖真香警告)

👉 江湖救急: mitt (毫无关系的组件怎么勾搭?用它!)

第一部分:咱们先捋捋,为什么通信这么让人头疼?

Vue 的设计哲学是“单向数据流”,这就像瀑布,水只能从上往下流。但写业务不是搞艺术,你总会遇到需要把下游的垃圾(数据)扔到上游去,或者两个完全不挨着的组件要共享状态。

很多新手(包括当年的我)的做法是:疯狂提升状态到父组件,然后通过 props 一层层往下灌。这在小型项目里没毛病,但在大型应用里,这种“Props 钻井”会让你崩溃。

第二部分:核心原理,当成水管工来理解

1. Props 与 Emits —— 你家卫生间的进水管和下水道

这是父子组件的标准对话方式。Props 是爹给儿子的钱(只读,别想篡改),Emits 是儿子喊爹帮忙办事(触发事件)。

// 父组件
<ChildComponent :name="userName" @update="handleUpdate" />

// 子组件
const props = defineProps(['name'])
const emit = defineEmits(['update'])
emit('update', newValue)

⚠️ 我踩过的坑:千万别在子组件里直接修改引用类型的 props (比如 props.obj.name = 'new' )。虽然对象引用不会报错,但这会让数据流乱成一锅粥,调试的时候哭都找不到调。

2. provide/inject —— 楼板打了个洞,直通楼下

你可能会问:“那我五层楼的组件怎么给一层传数据?” 好,咱们先来聊聊这个。

provide 就是顶层组件挖个洞,无论下面多少层子孙,只要通过 inject 伸个管子就能接到水。

再说个容易翻车的点:默认情况下,provide 的数据不是响应式的
如果你传了个普通数字,后面变了,楼下接到的还是旧的。要传 ref 或者 reactive 才行,或者用 Vue 3 提供的 computed 包一层。

3. v-model —— 双向对讲机,不是单向广播了

Vue 3 的 v-model 太好用了!它就是 :modelValue@update:modelValue 的语法糖。重点是现在可以绑定多个 v-model:title ,封装弹窗组件的时候香疯了。

4. mitt —— 那个满大街喊话的大喇叭

对于完全没有关系的组件(比如两个平级的菜单组件要联动),Vue 3 移除了全局事件总线,官方推荐用 mitt 这种第三方微型库。它就像个传呼台,A组件广播“喂喂喂我是XXX”,B组件随时待命收到。

❗️这里千万别学我当初偷懒,否则……否则项目上线后会发现内存泄漏,页面越用越卡。
mitt 最最最重要的一步:在组件销毁时(onBeforeUnmount)一定要 off 掉你监听的频道!

第三部分:实战,来段能跑的代码压压惊

接下来重点来了,看看 mitt 怎么用,别写错了:

// utils/eventBus.js
import mitt from 'mitt'
export const emitter = mitt()

// 组件A (发送)
import { emitter } from '@/utils/eventBus'
emitter.emit('send-message', { msg: 'Hello World' })

// 组件B (接收)
import { emitter } from '@/utils/eventBus'
import { onBeforeUnmount } from 'vue'

const handler = (data) => { console.log(data) }
emitter.on('send-message', handler)

// 必做!必做!必做!
onBeforeUnmount(() => {
  emitter.off('send-message', handler)
})

第四部分:最后啰嗦一句,怎么选?

是不是以为这样就完了?还没呢,光知道原理不够,得知道什么时候拔哪把刀。

- 父子组件、简单数据流: 老老实实 Props / Emits 。代码可读性第一。

- 深层嵌套(表单上下文、主题色): 首选 provide / inject 。别再用 props 穿针引线了。

- 组件封装(Input、Dialog): 无脑 v-model 。Vue 3 的语法糖真的甜。

- 跨视图、跨路由、无关组件: 如果项目小,用 mitt 足够了;如果项目大,直接上 Pinia,别拿 mitt 当全局状态仓库使,那是拿擀面杖当金箍棒,不趁手。


好啦,今天的组件通信“避坑指南”就聊到这。技术这玩意儿就是这样,原理说破了不值钱,但那个自己亲手把页面搞崩掉的坑,才是最宝贵的经验。

这篇东西花了好多心血整理的,如果你觉得有用,或者觉得以后大概率会用到,千万别让它就这么在收藏夹里吃灰。点赞+关注,转给那个还在用 Props 一层层嵌套的冤种同事,说不定今晚他能请你喝杯奶茶呢?☺️

老样子,有什么问题和想法,留言区里,咱们不见不散~ 👋


文章来源:https://www.cnblogs.com/ymtianyu/p/19878093
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐

标签云