Vue3 - defineExpose的使用
在 Vue 3 的 <script setup>
语法中,defineExpose
是一个特殊的编译宏,用于显式暴露组件内部的属性或方法,让父组件可以通过 ref 引用 访问到子组件的这些成员。
为什么需要 defineExpose
?
在 <script setup>
中,组件的内部状态(如变量、方法)默认是 私有 的,父组件无法直接通过 ref
访问。这是为了封装组件内部实现,避免外部随意修改。
如果父组件需要访问子组件的某些属性或方法,就必须通过 defineExpose
主动暴露。
基本用法
1. 子组件中使用 defineExpose
暴露成员
vue
<!-- 子组件 Child.vue -->
<script setup>
import { ref } from 'vue'// 内部状态
const count = ref(0)
const name = ref('子组件')// 内部方法
const increment = () => {count.value++
}// 暴露给父组件的成员(对象形式)
defineExpose({count, // 暴露响应式变量name, // 暴露响应式变量increment // 暴露方法
})
</script><template><div>子组件:count = {{ count }}</div>
</template>
2. 父组件通过 ref 访问子组件暴露的成员
vue
<!-- 父组件 Parent.vue -->
<script setup>
import { ref, onMounted } from 'vue'
import Child from './Child.vue'// 创建 ref 引用子组件
const childRef = ref(null)// 子组件挂载后才能访问(确保 ref 已指向子组件实例)
onMounted(() => {// 访问子组件暴露的属性console.log(childRef.value.name) // 输出:"子组件"console.log(childRef.value.count) // 输出:0// 调用子组件暴露的方法childRef.value.increment()console.log(childRef.value.count) // 输出:1
})
</script><template><Child ref="childRef" />
</template>
注意事项
-
访问时机:
父组件必须在子组件 挂载完成后 才能通过
ref
访问暴露的成员(可在onMounted
钩子中操作,或在模板中用可选链?.
避免初始化报错)。vue
<!-- 模板中安全访问 --> <div>子组件count:{{ childRef?.count }}</div>
-
响应式保持:
如果暴露的是
ref
或reactive
类型的响应式数据,父组件访问时仍能保持响应式(子组件修改后,父组件会自动更新)。 -
仅用于
<script setup>
:defineExpose
是<script setup>
特有的语法,普通的<script>
组件(非 setup 语法)不需要它,直接通过this
暴露即可。 -
暴露的是 “引用”:
父组件拿到的是子组件内部成员的引用,修改暴露的响应式数据会直接影响子组件(需谨慎操作,避免破坏组件封装性)。
总结
defineExpose
的核心作用是 打破 <script setup>
的默认私有性,让父组件能安全访问子组件的指定成员,适用于需要父子组件紧密交互的场景(如父组件调用子组件方法、获取子组件状态等)。