首页 / Vue3 入门教程 / 组件通信汇总

Vue3 入门教程

组件通信汇总

本教程共 40 篇 · 第 27 篇 · 更新于 2026-07-29 · 约 7 分钟阅读

VueVue3 入门教程组件通信PropsEventsv-modelProvide Inject

27. 组件通信汇总

本节目标:系统梳理 Vue 组件通信的所有方式,学会在不同场景下选择最合适的方案。

组件通信方式总览

方式方向跨层级适用场景
Props父 → 子父传数据给子
Events子 → 父子传消息给父
v-model双向表单类组件双向绑定
Provide / Inject祖先 → 后代跨层级传数据
$attrs父 → 子透传未声明属性
Pinia / Vuex任意任意全局状态管理

Props——父传子

最基础的通信方式。父组件通过属性传值,子组件用 defineProps() 接收:

<!-- 父组件 -->
<BlogPost :title="post.title" :author="post.author" />

<!-- 子组件 -->
<script setup>
const props = defineProps(['title', 'author'])
</script>

特点:单向数据流,prop 只读,类型可验证。

适用:绝大多数父子数据传递场景。

Events——子传父

子组件 emit 事件,父组件监听事件:

<!-- 子组件 -->
<button @click="$emit('delete', id)">删除</button>

<!-- 父组件 -->
<MyItem @delete="handleDelete" />

特点:事件不冒泡,只能监听直接子组件。

适用:子组件通知父组件做某事(删除、提交、切换等)。

v-model——父子双向绑定

语法糖,本质是 Props + Events 的组合:

<!-- 父组件 -->
<SearchInput v-model="keyword" />

<!-- 子组件 -->
<script setup>
const model = defineModel()
</script>

特点:自动同步,支持多个绑定和自定义修饰符。

适用:自定义表单组件,父子需要保持数据同步。

Provide / Inject——祖先到后代

跳过中间层级,直接跨级传递:

// 祖先
provide('theme', 'dark')

// 后代
const theme = inject('theme', 'light') // 默认值 'light'

特点:适合深层嵌套,提供方可把修改方法一起 provide。

适用:主题、用户信息、语言等全局但局部的共享数据。

Note

Provide / Inject 不是状态管理工具。它适合”某个组件树内部共享”,不适合整个应用的状态。

$attrs——透传属性

未声明为 prop 的属性自动传给子组件根元素:

<MyButton class="large" @click="handler" />

class@click 没被声明为 prop,就会透传。用 inheritAttrs: false 关闭自动继承后,可以手动控制:

<button v-bind="$attrs">Click</button>

特点:适合做”透明包装组件”,把属性透传给内部元素。

适用:封装第三方组件、高阶组件。

怎么选择

按场景一步步判断:

  1. 父传子数据 → Props
  2. 子传父消息 → Events
  3. 表单双向同步 → v-model
  4. 跨多层传数据 → Provide / Inject
  5. 透传属性给内部元素 → $attrs
  6. 全局应用状态 → Pinia / Vuex

一个综合例子

假设一个 UserCard 组件,展示用户名和头像,点击可以展开详情:

<!-- 祖先:App.vue -->
<script setup>
import { provide } from 'vue'
provide('theme', 'dark')
</script>

<!-- 中间层:UserList.vue -->
<!-- 不用管 theme,也不需要传 -->

<!-- 后代:UserCard.vue -->
<script setup>
import { inject } from 'vue'

// 跨级注入主题
const theme = inject('theme')

// Props 接收数据
const props = defineProps({
  name: String,
  avatar: String
})

// Events 通知父组件
const emit = defineEmits(['expand'])

// v-model 双向绑定
const model = defineModel()
</script>

一个组件里经常多种通信方式同时使用——这不是”选一个”,而是”各管各的”。

常见误区

误区正确做法
所有数据都用 props 层层传递跨层用 Provide / Inject
跨层级也用 Events 冒泡事件不冒泡,用 provide 函数或状态管理
Provide / Inject 替代 Pinia它们定位不同,不是替代关系
每个组件都全局注册大多数组件局部注册

本节回顾

  • Props 父传子,Events 子传父,两者组合是最常用的
  • v-model 是 Props + Events 的语法糖,适合表单组件
  • Provide / Inject 解决跨层级传递
  • $attrs 做属性透传
  • 全局状态用专门的库(Pinia)
  • 一个组件可以同时使用多种通信方式