子组件必须用 defineexpose 显式暴露方法,父组件通过 ref 调用;defineexpose 需在 顶层调用,传入对象声明可访问项,支持 ref、computed 和函数,未暴露则不可见。

在 Vue 3 的 <script setup></script> 中,子组件默认不对外暴露任何变量或函数,父组件通过 ref 拿到的只是一个“空壳”实例。要让父组件能调用子组件的方法,必须用 defineExpose 显式声明可访问项。
子组件中怎么写 defineExpose
直接在 <script setup></script> 顶层调用,传入一个对象,键是对外暴露的名称,值是你定义的响应式变量、计算属性或函数:
- 支持
ref、computed、普通函数(含异步函数) - 同名简写:
defineExpose({ reset, validate }) - 重命名暴露:
defineExpose({ clearForm: reset, check: validate }) - 不能写在函数、条件语句或
onMounted等钩子里,必须是顶层语句 - 无需导入,它是编译宏,不是运行时函数
示例:
使用 `@ainative/vue-sdk` 为 Vue 3 应用添加 AI 聊天功能。适用于以下场景:(1) 安装 `@ainative/vue-sdk`,(2) 在 Vue 组件中使用 `useChat` 组合式函数,(3) 提供……
<script setup><br> import { ref } from '<a style="color:#f60; text-decoration:underline;" title= "vue"href="https://m.php.cn/zt/15721.html" target="_blank">vue'<br> const count = ref(0)<br> function reset() { count.value = 0 }<br> function validate() { return count.value > 0 }<br> <strong>defineExpose({ reset, validate })<br> </script>
父组件怎么安全调用暴露的方法
父组件需确保子组件已挂载,并通过绑定的 ref 访问暴露后的实例:
- 模板中用
<child ref="childRef"></child> - 脚本中声明
const childRef = ref(null) - 在
onMounted或事件回调中调用,避免访问null - 调用时直接使用
childRef.value.reset(),无需.value后缀(函数本身不自动解包,但调用方式就是标准函数调用) - 建议加空值判断:
if (childRef.value) childRef.value.reset()
示例:
<script setup><br> import { ref, onMounted } from 'vue'<br> import Child from './Child.vue'<br> const childRef = ref(null)<br> onMounted(() => {<br> childRef.value?.reset()<br> })<br> </script>
暴露方法时的关键细节
defineExpose 不是“导出”,而是“授权访问”。它决定父组件能看到什么、能调用什么:
- 未被包含的函数,哪怕写得再完整,在父组件里也完全不可见
- 暴露的
ref在父组件读取时自动解包(如childRef.value.count是数字,不是Ref对象) - 暴露的函数内部
this指向子组件实例,可正常访问其他暴露项或内部逻辑 - TypeScript 用户建议配合接口标注,提升类型推导准确性:
interface ChildExposed { reset: () => void; validate: () => boolean }
defineExpose({ reset, validate })
常见误区提醒
- 误以为
ref绑定后就能直接调用——没defineExpose就是空对象 - 在
setup()函数里或if分支中调用defineExpose——会报编译错误 - 暴露未定义的变量,比如写
defineExpose({ doSomething })却没声明doSomething函数 - 忽略挂载时机,在
onMounted外直接访问childRef.value,导致undefined报错
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









