父组件通过ref访问子组件属性需满足两点:子组件用defineExpose显式暴露,父组件在onMounted中通过ref.value安全读取;ref类型属性自动解包,普通响应式对象保持响应式。

父组件通过 ref 访问子组件暴露的属性,核心就两点:子组件必须用 defineExpose 显式声明要对外公开的内容,父组件在组件挂载后才能通过 ref.value 安全读取。
子组件必须主动暴露属性
Vue 3 的 <script setup> 默认是封闭的——哪怕父组件拿到了子组件实例,也看不到任何内部变量或方法。所以暴露不是可选项,而是必要步骤。
- 用
ref或reactive声明需要共享的响应式数据(比如const count = ref(0)) - 在子组件末尾调用
defineExpose({ count, name, isActive }),传入一个对象,键名就是父组件将看到的属性名 - 注意:ref 类型的属性会被自动解包,父组件访问时直接拿到
.value后的值,不需要再写.value
父组件正确声明和使用 ref
模板中加 ref="xxx" 只是标记,真正起作用的是脚本中同名的 ref(null) 变量。
- 在父组件
<script setup>中定义:const childRef = ref(null)(初始值必须为null) - 模板中对应写:
<ChildComponent ref="childRef" />(名字必须完全一致) - 不能在
setup函数体里直接访问childRef.value,因为此时子组件还没挂载;需放在onMounted钩子中判断是否存在
访问暴露的属性要等挂载完成
子组件实例只有在挂载后才真正可用,否则 childRef.value 是 null。
立即学习“前端免费学习笔记(深入)”;
- 在
onMounted(() => { ... })中检查:if (childRef.value) { /* 安全访问 */ } - 读取 ref 类型属性:
childRef.value.count→ 直接得到数字 0(不是 ref 对象) - 读取普通响应式对象:
childRef.value.userInfo→ 得到 reactive 包裹的对象,仍保持响应式 - 如果想修改暴露的 ref 属性,仍要通过
.value赋值:childRef.value.count = 100
常见错误提醒
这些细节不注意,很容易报错或读不到值:
- 子组件漏写
defineExpose→ 父组件拿到的是空对象{} - 父组件 ref 变量名和模板中
ref="xxx"不一致 →ref始终为null - 在
setup顶层直接访问childRef.value.xxx→ 报 “Cannot read property 'xxx' of null” - 暴露了函数但没暴露对应的数据 → 函数能调,但返回值依赖的内部状态父组件无法同步观察


















