【Vue3 实战系列·第 02 篇】组件通信:Props·Emit·Provide/Inject·v-model——从父子到跨层级的通信全景
【Vue3 实战系列·第 02 篇】组件通信:Props·Emit·Provide/Inject·v-model——从父子到跨层级的通信全景
系列回顾:第 01 篇我们掌握了组合式 API 的核心——ref/reactive/computed/watch/Composables,从选项式到组合式的思维转换。本篇进入 Vue3 实战的第二个核心话题:组件通信。任何非平凡的 Vue 应用都由多个组件组成,组件之间必须通信——父传子数据、子通知父事件、跨层级共享状态、双向绑定表单值、父组件调用子组件方法。Vue3 提供了丰富的通信方式:Props Down / Events Up是黄金法则——数据从父到子(Props),事件从子到父(Emit),单向数据流保证可追踪性;Provide/Inject跳过中间层——祖先直接给深层后代传数据,不需要逐层转发 Props;v-model / defineModel实现双向绑定——表单控件的标准模式,Vue 3.4 的 defineModel 让代码更简洁;ref + expose让父组件调用子组件方法——命令式调用的场景。选择哪种通信方式?有一个简单的决策树:父子通信用 Props+Emit,双向绑定用 v-model,跨层级用 Provide/Inject,全局状态用 Pinia。今天,我们从 Props/Emit、Provide/Inject 到 v-model/defineModel,彻底掌握 Vue3 组件通信。
📑 文章目录
- ⬇️ 一、Props 与 Emit:Props Down / Events Up
- 💉 二、Provide / Inject:跳过中间层
- 🔗 三、v-model / defineModel / ref+expose:高级通信
⬇️ 一、Props 与 Emit:Props Down / Events Up
1.1 Props:父传子的数据通道
Props 是 Vue 组件通信的基础——父组件通过 Props 向子组件传递数据。子组件必须显式声明它接收哪些 Props,未声明的属性会作为"透传属性"(Fallthrough Attributes)处理。
<!-- 子组件 UserCard.vue --> <script setup lang="ts"> // 泛型方式声明 Props(推荐) const props = defineProps<{ name: string age: number avatar?: string // 可选 role?: 'admin' | 'user' // 联合类型 }>() // 运行时方式声明(带默认值) const props = withDefaults(defineProps<{ name: string age: number avatar?: string }>(), { avatar: '/default-avatar.png', }) </script> <template> <div class="user-card"> <img :src="avatar" :alt="name" /> <h3>{{ name }}</h3> <span>{{ age }}岁</span> </div> </template><!-- 父组件 --> <script setup> import UserCard from './UserCard.vue' </script> <template> <UserCard name="张三" :age="25" avatar="/zhangsan.png" /> </template>Props 的核心原则:单向数据流——子组件不能修改 Props。这是 Vue 最重要 … | 跨层级通信 | Provide/Inject(深层嵌套/主题/配置/权限) |
| 全局状态 | Pinia(下一篇)——多组件共享状态 |
选择原则
能用 Props+Emit 就用 → 需要双向用 v-model → 跨层级用 Provide/Inject → 全局用 Pinia
Vue3 实战系列进度
| 篇号 | 主题 | 核心内容 | 状态 |
|---|---|---|---|
| 01 | 组合式API | ref/reactive/computed/watch/Composables | ✅ |
| 02 | 组件通信(本文) | props/emit/provide-inject/v-model | ✅ |
| 03 | Pinia状态管理 | Store/Action/持久化/模块化 | ⏳ 下一篇 |
| 04 | Router路由 | 动态路由/守卫/懒加载 | 待写 |
| 05 | 性能优化 | 虚拟列表/异步组件/SSR | 待写 |
| 06 | TypeScript+Vue3 | 类型安全/泛型组件/类型推导 | 待写 |
一句话总结
Vue3 组件通信三大层次:Props 与 Emit(Props Down / Events Up 黄金法则——数据从父到子Props只读单向数据流保证可追踪/事件从子到父Emit通知父组件修改。defineProps泛型声明+withDefaults默认值/defineEmits泛型声明。常见陷阱=直接修改props/对象引用共享/类型不声明。Props+Emit是默认选择简单可预测易调试)、Provide/Inject(跳过中间层——祖先组件provide数据任意深层后代inject使用无需逐层转发。关键保护=用readonly()包裹provide的值防止后代意外修改。最佳实践=provide响应式数据+readonly+修改方法"数据只读方法可调"。适用场景=深层嵌套组件主题/配置/权限+插件/库不污染props。vs Props逐层传递=代码量固定不变但可追踪性稍弱)、高级通信(v-model组件双向绑定——Props+emit的语法糖:modelValue+@update:modelValue。defineModel Vue 3.4+极简写法一行代码搞定双向绑定支持多个v-model:name/v-model:age。ref+expose父组件调用子组件方法——子组件defineExpose暴露方法/父组件通过template ref获取实例调用。选择决策树=父子通信用Props+Emit→双向绑定用v-model→跨层级用Provide/Inject→全局用Pinia)。
参考链接:
- Vue3 Props
- Vue3 Component Events
- Vue3 Provide/Inject
- Vue3 Component v-model
- Vue3 defineModel (3.4+)
