Vue 3 中父组件需通过 defineExpose 显式暴露子组件的变量和方法才能访问,否则 ref 获取的实例不包含 setup 内定义的内容;子组件在 中调用 defineExpose({}) 暴露响应式数据或函数,父组件在 onMounted 后通过 childRef.value 调用。

在 Vue 3 的组合式 API 中,父组件无法直接访问子组件的内部变量或方法,必须通过 defineExpose 主动暴露才能被获取。这是 Vue 3 相比 Vue 2 的重要变化,也是实现父子通信的关键一环。
为什么需要 defineExpose?
Vue 3 默认隐藏了子组件的实例(ref 拿到的是代理对象,不包含 setup 中定义的响应式变量或函数)。如果不显式暴露,父组件调用 childRef.value.xxx 会报错或返回 undefined。
只有使用 defineExpose 明确导出的内容,才会出现在子组件实例上,供父组件安全调用。
如何在子组件中使用 defineExpose?
在子组件的 <script setup></script> 中,调用 defineExpose 并传入一个对象,列出你想对外公开的属性或方法:
- 可以暴露响应式数据(如
ref、computed) - 可以暴露普通函数(含异步函数)
- 不能暴露未声明的变量,也不能暴露未通过
return或defineExpose导出的内部逻辑
示例(子组件 Child.vue):
从零开始编排 SpringBoot+Vue 全栈项目工作流,适用于新建全栈项目或完整脚手架请求,触发后依次调用 product‑spec‑builder(需求调研)等模块。
<script setup>
import { ref, computed } from 'vue'
<p>const count = ref(0)
const message = ref('Hello')<p>const increment = () => {
count.value++
}<p>const double = computed(() => count.value * 2)<p>// ✅ 主动暴露给父组件
defineExpose({
count,
message,
increment,
double
})
</script>父组件如何获取并调用子组件实例?
父组件需配合 ref 和 onMounted(或 v-if 控制时机),确保子组件已挂载后再访问:
- 用
ref绑定子组件标签,如 - 在
onMounted中访问childRef.value,它就是暴露后的实例对象 - 可直接调用暴露的方法,或读写暴露的响应式属性
示例(父组件):
<script setup>
import { ref, onMounted } from 'vue'
import Child from './Child.vue'
<p>const childRef = ref(null)<p>onMounted(() => {
console.log(childRef.value.count.value) // 0
console.log(childRef.value.double.value) // 0
childRef.value.increment() // 触发子组件逻辑
console.log(childRef.value.count.value) // 1
})
</script><p><template><child ref="childRef"></child></template></p>常见注意事项
-
暴露的是响应式引用本身:比如暴露
count(一个ref),父组件拿到后仍需通过.value访问或修改 - 避免暴露过多内部细节:只暴露必要的接口,保持子组件封装性
-
动态暴露不支持:
defineExpose只能在顶层同步调用,不能放在条件语句或函数中 - TS 类型提示友好:暴露的对象结构会被 TypeScript 自动推导,父组件中能获得完整类型支持
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










