在 Vue3 项目开发中组件通信是核心基本功。很多同学只会props/emit遇到兄弟组件、深层嵌套组件、全局状态交互就无从下手。本文整理Vue3 所有 9 种组件通信方式覆盖父子、跨层级、兄弟、全局所有场景全部基于最新script setup语法附带可直接运行代码、适用场景、优缺点、避坑指南一文彻底吃透 Vue3 组件传值。一、Vue3 组件通信总览9种全覆盖通信方式传输方向适用场景核心特点defineProps父 ➜ 子普通父子传值单向数据流、可校验、响应式defineEmits子 ➜ 父子组件触发事件回传数据事件驱动、无数据污染v-model父 ⬌ 子 双向表单、弹窗、数值同步语法糖简化双向绑定ref defineExpose父 ➜ 子调用方法/取值父主动获取子组件实例、调用子方法精准控制、适合实例操作$attrs父 ➜ 后代 跨层透传多层嵌套传参、无需逐层转发自动透传、不占用propsprovide / inject祖先 ➜ 所有后代深层嵌套全局配置、主题、权限跨N层组件、支持响应式mitt 事件总线任意组件互通兄弟组件、非关联组件简单通信轻量、灵活、适合简单场景Pinia任意组件全局互通全局状态、复杂数据、多组件共享Vue3官方状态管理、响应式、可模块化父级中间层中转兄弟组件互通简单兄弟通信过渡方案低成本、适合少量交互二、父子组件通信最常用 4 种1. defineProps 父传子单向下传场景父组件向子组件传递展示数据、配置参数核心规则单向数据流子组件禁止直接修改 props父组件template Child :titletitle :listlist / /template script setup import { ref } from vue import Child from ./Child.vue const title ref() const list ref([1,2,3]) /script子组件规范校验写法script setup // 企业级规范类型默认值必填 const props defineProps({ title: { type: String, required: true }, list: { type: Array, default: () [] // 引用类型必须函数返回 } }) /script2. defineEmits 子传父事件上报场景子组件点击、输入、操作后把数据回传给父组件子组件template button clickhandleSend回传数据给父组件/button /template script setup const emit defineEmits([onSubmit]) const handleSend () { emit(onSubmit, 子组件数据, 666) } /script父组件template Child onSubmithandleSubmit / /template script setup const handleSubmit (str, num) { console.log(str, num) } /script3. v-model 父子双向绑定场景弹窗显隐、输入框、数值双向同步Vue3 支持多 v-model告别 .sync 修饰符父组件template Child v-model:visibledialogVisible v-model:countnum / /template script setup import { ref } from vue const dialogVisible ref(false) const num ref(0) /script子组件script setup const props defineProps([visible, count]) const emit defineEmits([update:visible, update:count]) const closeDialog () { emit(update:visible, false) } const addCount () { emit(update:count, props.count 1) } /script4. ref defineExpose 父调用子方法/取值场景父组件主动调用子组件的方法、获取子组件内部数据setup 默认关闭实例暴露必须手动defineExpose子组件script setup import { ref } from vue const msg ref(子组件内部数据) const childFn () { console.log(子组件方法被调用) } // 暴露给父组件 defineExpose({ msg, childFn }) /script父组件template Child refchildRef / /template script setup import { ref, onMounted } from vue import Child from ./Child.vue const childRef ref(null) onMounted(() { // 调用子组件方法、取值 childRef.value.childFn() console.log(childRef.value.msg) }) /script三、跨层级组件通信2种1. $attrs 自动属性透传场景多层嵌套组件父组件参数无需逐层手动传递特点自动透传所有非 props 属性、事件、class、style父组件最外层GrandChild title标题透传 :timetime /深层子组件直接接收template div{{ $attrs.title }} {{ $attrs.time }}/div /template2. provide / inject 祖先向后代全局注入场景主题色、全局配置、用户信息、权限、多层嵌套通用数据优势无视层级任意后代组件均可取值支持响应式祖先组件提供数据script setup import { ref, provide } from vue const theme ref(dark) const userInfo ref({ name: admin, role: admin }) // 注入全局数据 provide(theme, theme) provide(user, userInfo) /script任意后代组件接收数据script setup import { inject } from vue const theme inject(theme) const user inject(user) /script注意传入 ref/reactive 可保持响应式普通变量无响应式四、兄弟组件 / 任意组件通信2种1. Mitt 轻量事件总线简单场景首选场景兄弟组件、无关联组件简单消息通知、数据交互Vue3 移除了原生 bus推荐使用mitt安装 封装 bus.jsnpminstallmitt// src/utils/bus.jsimportmittfrommittexportconstemittermitt()组件A发送方script setup import { emitter } from /utils/bus // 触发事件 emitter.emit(refreshList, 我是A组件数据) /script组件B接收方script setup import { emitter } from /utils/bus import { onMounted, onUnmounted } from vue // 监听事件 onMounted(() { emitter.on(refreshList, (data) { console.log(接收数据, data) }) }) // 销毁监听防内存泄漏 onUnmounted(() { emitter.off(refreshList) }) /script2. Pinia 全局状态管理复杂项目首选场景全局共享数据、复杂状态、多组件频繁读写、持久化数据Vue3 官方替代 Vuex极简、轻量化、类型友好定义 store// src/stores/user.jsimport{defineStore}frompiniaexportconstuseUserStoredefineStore(user,{state:()({userName:,token:}),actions:{setUser(name){this.userNamename}}})任意组件使用script setup import { useUserStore } from /stores/user const userStore useUserStore() // 改数据 userStore.setUser(前端开发者) // 取数据 console.log(userStore.userName) /script五、极简方案父组件中转兄弟通信场景临时少量兄弟交互不想装插件、不写状态管理兄弟A 通过 emit 把数据传给父组件父组件接收数据、更新自身状态父组件通过 props 传给兄弟B缺点多层嵌套会产生 props 层层穿透复杂项目不推荐六、各通信方式最佳场景选型实战必看普通父子传值props / emit / v-model父调用子方法ref defineExpose深层嵌套传全局配置provide / inject多层属性透传$attrs简单兄弟/跨组件通知mitt 事件总线全局共享、复杂状态Pinia七、高频避坑总结禁止直接修改 props破坏单向数据流Vue3 直接报错mitt 必须手动销毁监听否则造成内存泄漏provide 普通变量无响应式必须传 ref/reactivesetup 组件默认不暴露实例必须 defineExpose 父组件才能调用复杂业务坚决用 Pinia少用 bus 和多层 props 穿透八、结尾Vue3 的 9 种组件通信方式覆盖了所有业务场景简单父子交互用基础API、跨层用 provide/inject、兄弟简单通信用 mitt、全局状态统一用 Pinia。
Vue3 组件通信 9 种方式详解
发布时间:2026/7/11 5:20:36
在 Vue3 项目开发中组件通信是核心基本功。很多同学只会props/emit遇到兄弟组件、深层嵌套组件、全局状态交互就无从下手。本文整理Vue3 所有 9 种组件通信方式覆盖父子、跨层级、兄弟、全局所有场景全部基于最新script setup语法附带可直接运行代码、适用场景、优缺点、避坑指南一文彻底吃透 Vue3 组件传值。一、Vue3 组件通信总览9种全覆盖通信方式传输方向适用场景核心特点defineProps父 ➜ 子普通父子传值单向数据流、可校验、响应式defineEmits子 ➜ 父子组件触发事件回传数据事件驱动、无数据污染v-model父 ⬌ 子 双向表单、弹窗、数值同步语法糖简化双向绑定ref defineExpose父 ➜ 子调用方法/取值父主动获取子组件实例、调用子方法精准控制、适合实例操作$attrs父 ➜ 后代 跨层透传多层嵌套传参、无需逐层转发自动透传、不占用propsprovide / inject祖先 ➜ 所有后代深层嵌套全局配置、主题、权限跨N层组件、支持响应式mitt 事件总线任意组件互通兄弟组件、非关联组件简单通信轻量、灵活、适合简单场景Pinia任意组件全局互通全局状态、复杂数据、多组件共享Vue3官方状态管理、响应式、可模块化父级中间层中转兄弟组件互通简单兄弟通信过渡方案低成本、适合少量交互二、父子组件通信最常用 4 种1. defineProps 父传子单向下传场景父组件向子组件传递展示数据、配置参数核心规则单向数据流子组件禁止直接修改 props父组件template Child :titletitle :listlist / /template script setup import { ref } from vue import Child from ./Child.vue const title ref() const list ref([1,2,3]) /script子组件规范校验写法script setup // 企业级规范类型默认值必填 const props defineProps({ title: { type: String, required: true }, list: { type: Array, default: () [] // 引用类型必须函数返回 } }) /script2. defineEmits 子传父事件上报场景子组件点击、输入、操作后把数据回传给父组件子组件template button clickhandleSend回传数据给父组件/button /template script setup const emit defineEmits([onSubmit]) const handleSend () { emit(onSubmit, 子组件数据, 666) } /script父组件template Child onSubmithandleSubmit / /template script setup const handleSubmit (str, num) { console.log(str, num) } /script3. v-model 父子双向绑定场景弹窗显隐、输入框、数值双向同步Vue3 支持多 v-model告别 .sync 修饰符父组件template Child v-model:visibledialogVisible v-model:countnum / /template script setup import { ref } from vue const dialogVisible ref(false) const num ref(0) /script子组件script setup const props defineProps([visible, count]) const emit defineEmits([update:visible, update:count]) const closeDialog () { emit(update:visible, false) } const addCount () { emit(update:count, props.count 1) } /script4. ref defineExpose 父调用子方法/取值场景父组件主动调用子组件的方法、获取子组件内部数据setup 默认关闭实例暴露必须手动defineExpose子组件script setup import { ref } from vue const msg ref(子组件内部数据) const childFn () { console.log(子组件方法被调用) } // 暴露给父组件 defineExpose({ msg, childFn }) /script父组件template Child refchildRef / /template script setup import { ref, onMounted } from vue import Child from ./Child.vue const childRef ref(null) onMounted(() { // 调用子组件方法、取值 childRef.value.childFn() console.log(childRef.value.msg) }) /script三、跨层级组件通信2种1. $attrs 自动属性透传场景多层嵌套组件父组件参数无需逐层手动传递特点自动透传所有非 props 属性、事件、class、style父组件最外层GrandChild title标题透传 :timetime /深层子组件直接接收template div{{ $attrs.title }} {{ $attrs.time }}/div /template2. provide / inject 祖先向后代全局注入场景主题色、全局配置、用户信息、权限、多层嵌套通用数据优势无视层级任意后代组件均可取值支持响应式祖先组件提供数据script setup import { ref, provide } from vue const theme ref(dark) const userInfo ref({ name: admin, role: admin }) // 注入全局数据 provide(theme, theme) provide(user, userInfo) /script任意后代组件接收数据script setup import { inject } from vue const theme inject(theme) const user inject(user) /script注意传入 ref/reactive 可保持响应式普通变量无响应式四、兄弟组件 / 任意组件通信2种1. Mitt 轻量事件总线简单场景首选场景兄弟组件、无关联组件简单消息通知、数据交互Vue3 移除了原生 bus推荐使用mitt安装 封装 bus.jsnpminstallmitt// src/utils/bus.jsimportmittfrommittexportconstemittermitt()组件A发送方script setup import { emitter } from /utils/bus // 触发事件 emitter.emit(refreshList, 我是A组件数据) /script组件B接收方script setup import { emitter } from /utils/bus import { onMounted, onUnmounted } from vue // 监听事件 onMounted(() { emitter.on(refreshList, (data) { console.log(接收数据, data) }) }) // 销毁监听防内存泄漏 onUnmounted(() { emitter.off(refreshList) }) /script2. Pinia 全局状态管理复杂项目首选场景全局共享数据、复杂状态、多组件频繁读写、持久化数据Vue3 官方替代 Vuex极简、轻量化、类型友好定义 store// src/stores/user.jsimport{defineStore}frompiniaexportconstuseUserStoredefineStore(user,{state:()({userName:,token:}),actions:{setUser(name){this.userNamename}}})任意组件使用script setup import { useUserStore } from /stores/user const userStore useUserStore() // 改数据 userStore.setUser(前端开发者) // 取数据 console.log(userStore.userName) /script五、极简方案父组件中转兄弟通信场景临时少量兄弟交互不想装插件、不写状态管理兄弟A 通过 emit 把数据传给父组件父组件接收数据、更新自身状态父组件通过 props 传给兄弟B缺点多层嵌套会产生 props 层层穿透复杂项目不推荐六、各通信方式最佳场景选型实战必看普通父子传值props / emit / v-model父调用子方法ref defineExpose深层嵌套传全局配置provide / inject多层属性透传$attrs简单兄弟/跨组件通知mitt 事件总线全局共享、复杂状态Pinia七、高频避坑总结禁止直接修改 props破坏单向数据流Vue3 直接报错mitt 必须手动销毁监听否则造成内存泄漏provide 普通变量无响应式必须传 ref/reactivesetup 组件默认不暴露实例必须 defineExpose 父组件才能调用复杂业务坚决用 Pinia少用 bus 和多层 props 穿透八、结尾Vue3 的 9 种组件通信方式覆盖了所有业务场景简单父子交互用基础API、跨层用 provide/inject、兄弟简单通信用 mitt、全局状态统一用 Pinia。