在 Vue3 开发中,父子组件通信是最基础也最核心的技能,不管是简单页面还是复杂项目,都离不开父子组件的数据传递与事件交互。
这篇博客会用最通俗的语言,结合 <script setup> 语法(Vue3 推荐写法),把6种常用父子组件通信方案讲透,从基础到进阶,看完就能直接上手用!
简单说:在父组件中引入并使用的组件,就是子组件。
比如:父组件 Father.vue 里写了 <Child />,那 Father 就是父组件,Child 就是子组件。
通信核心场景:
最基础、最常用:父组件通过属性传值,子组件用 defineProps 接收(只读,不能直接修改)。
xml 体验AI代码助手 代码解读复制代码<template>
<div class="father">
<h3>父组件</h3>
<!-- 向子组件传值:msg、list、user -->
<Child
msg="我是父组件传的字符串"
:list="['Vue3', 'React', 'Angular']"
:user="{ name: '张三', age: 20 }"
/>
</div>
</template>
<script setup>
// 引入子组件
import Child from './Child.vue'
</script>xml 体验AI代码助手 代码解读复制代码<template>
<div class="child">
<h4>子组件</h4>
<p>字符串:{{ msg }}</p>
<p>数组:{{ list[0] }}</p>
<p>对象:{{ user.name }}</p>
</div>
</template>
<script setup>
// 1. defineProps 接收父组件传的值(Vue3 <script setup> 专属)
// 2. 支持类型校验、默认值、必传校验
const props = defineProps({
// 基础类型校验
msg: String,
// 复杂类型 + 默认值
list: {
type: Array,
default: () => []
},
// 必传参数
user: {
type: Object,
required: true
}
})
// 直接使用 props.xxx 访问数据
console.log(props.msg)
</script>核心要点:
子组件不能直接修改父组件数据,需要触发自定义事件,把数据回传给父组件。
xml 体验AI代码助手 代码解读复制代码<template>
<button @click="sendToFather">点击给父组件传值</button>
</template>
<script setup>
// 1. 定义要触发的事件名(和自定义事件名一致)
const emit = defineEmits(['child-event'])
const sendToFather = () => {
// 2. 触发事件:emit(事件名, 传递的数据1, 数据2...)
emit('child-event', '我是子组件回传的消息', 666)
}
</script>xml 体验AI代码助手 代码解读复制代码<template>
<Child @child-event="handleChild" />
</template>
<script setup>
import Child from './Child.vue'
// 接收子组件回传的数据
const handleChild = (msg, num) => {
console.log('父组件收到:', msg, num) // 我是子组件回传的消息 666
}
</script>核心要点:
父组件想直接调用子组件的方法、获取子组件数据,用 ref + defineExpose。
xml 体验AI代码助手 代码解读复制代码<script setup>
import { ref } from 'vue'
// 子组件数据
const childMsg = ref('我是子组件数据')
// 子组件方法
const childFn = () => {
alert('子组件方法被父组件调用了!')
}
// 关键:必须用 defineExpose 暴露,父组件才能访问
defineExpose({
childMsg,
childFn
})
</script>xml 体验AI代码助手 代码解读复制代码<template>
<Child ref="childRef" />
<button @click="callChild">父组件调用子组件</button>
</template>
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
// 1. 创建 ref,名字和子组件上的 ref 一致
const childRef = ref(null)
const callChild = () => {
// 2. 通过 childRef.value 访问子组件暴露的内容
childRef.value.childFn() // 调用子组件方法
console.log(childRef.value.childMsg) // 获取子组件数据
}
</script>核心要点:
defineExpose 主动暴露,父组件才能获取Vue3.4+ 新增 defineModel,一行代码实现父子数据双向同步,比传统 v-model 更简洁!
xml 体验AI代码助手 代码解读复制代码<template>
<!-- 直接绑定 modelValue,修改会自动同步到父组件 -->
<input v-model="modelValue" placeholder="输入同步到父组件" />
</template>
<script setup>
// 一行代码搞定双向绑定,无需 defineProps + defineEmits
const modelValue = defineModel()
</script>xml 体验AI代码助手 代码解读复制代码<template>
<p>父组件数据:{{ inputVal }}</p>
<!-- v-model 绑定,子组件修改会自动更新这里 -->
<Child v-model="inputVal" />
</template>
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
const inputVal = ref('')
</script>核心要点:
defineModel,极简写法首选如果父组件有多层子组件(父→子→孙),用 props 太麻烦,直接用 provide 传值,后代用 inject 接收。
xml 体验AI代码助手 代码解读复制代码<script setup>
import { ref, provide } from 'vue'
import Child from './Child.vue'
const fatherData = ref('我是父组件跨级传的值')
// provide(键名, 数据)
provide('FATER_DATA', fatherData)
</script>xml 体验AI代码助手 代码解读复制代码<template>
<p>孙组件接收:{{ data }}</p>
</template>
<script setup>
import { inject } from 'vue'
// inject(键名) 直接接收
const data = inject('FATER_DATA')
</script>核心要点:
父组件直接把自己的方法通过 props 传给子组件,子组件直接调用。https://bjs.my.canvasite.cn/ https://tj.my.canvasite.cn/ https://shp.my.canvasite.cn/ https://zqs.my.canvasite.cn/
xml 体验AI代码助手 代码解读复制代码<script setup>
import Child from './Child.vue'
// 父组件方法
const fatherFn = (val) => {
alert('父组件方法被调用,值:' + val)
}
</script>
<template>
<!-- 把方法传给子组件 -->
<Child :father-fn="fatherFn" />
</template>xml 体验AI代码助手 代码解读复制代码<script setup>
// 接收方法
const props = defineProps({
fatherFn: Function
})
// 直接调用
const useFatherFn = () => {
props.fatherFn('子组件调用')
}
</script>核心要点:
emit场景 | 推荐方案 | 优先级 |
|---|---|---|
父→子 传普通数据 | props / defineProps | 最高 |
子→父 回传数据 | defineEmits | 最高 |
父调用子方法/数据 | ref + defineExpose | 中 |
父子数据双向同步 | v-model / defineModel | 高 |
父→后代 跨级传值 | provide / inject | 中 |
简单传函数 | props 传方法 | 低 |
Vue3 父子组件通信核心就 3 句话:
props(基础)、v-model(双向)、provide(跨级)defineEmits 触发事件ref + defineExpose所有方案都基于 <script setup> 写法,是 Vue3 最新、最简洁的实践,日常开发掌握前 4 种就足够应对 90% 场景!
props + emit,双向绑定用 defineModel,跨级用 provide/injectdefineExpose,这是 Vue3 <script setup> 的强制规则原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。