defineExpose 是 Vue 3 中父组件通过 ref 访问子组件方法的唯一标准方式,需在 顶层调用,支持同名暴露、重命名和计算值,应仅暴露必要命令式能力,并配合 TypeScript 接口确保类型安全。

Vue 3 单文件组件中,defineExpose 是唯一标准方式,用于让父组件通过 ref 访问子组件内部的方法。不调用它,父组件拿到的子组件实例就是空对象,所有方法都不可见。
子组件里怎么写 defineExpose
必须放在 <script setup></script> 的顶层,不能包在函数或条件语句里。语法简洁,支持同名简写、重命名和动态值:
- 同名暴露:
defineExpose({ validate, reset }) - 重命名暴露:
defineExpose({ doValidate: validate, clear: reset }) - 暴露计算值:
defineExpose({ isReady: computed(() => dataLoaded.value) })
注意:不能直接暴露未声明的变量,也不能暴露响应式包装器本身(如 computed 需先解包或用 computed 包一层再暴露)。
哪些方法值得暴露
只暴露父组件真正需要的命令式能力,保持封装性:
- 校验类:如
validate()、checkForm() - 操作类:如
focusInput()、startUpload()、openDialog() - 状态获取类:如
getFiles()、getCurrentValue() - 重置类:如
reset()、clearCache()
避免暴露临时变量、内部工具函数或与业务无关的逻辑。
父组件怎么安全调用
必须确保子组件已挂载,且检查 ref.value 是否存在:
- 模板中绑定:
- 脚本中声明:
const childRef = ref(null) - 在
onMounted或事件回调中调用:if (childRef.value) { childRef.value.validate() }
SSR 或未挂载时 childRef.value 是 null,直接访问会报错。
TypeScript 类型提示增强
搭配接口定义可获得完整类型推导,避免 any:
- 定义接口:
interface ChildExposed { validate: () => boolean; reset: () => void; } - 暴露时标注:
defineExpose({ validate, reset }) - 父组件中
childRef.value.validate()就有自动补全和类型校验
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










