Vue3 expose() 函数
Vue 3 中的 expose() 函数是 Composition API 提供的一个重要工具,用于在组件中控制哪些方法或属性可以被父组件访问。它是用来替代 Vue 2 中 this.$emit 和 this.$expose 等方式的一种更现代、更清晰的写法。
核心概念
在 Vue 3 的组件中,使用 <script setup> 语法时,组件对外暴露的 API 默认是不包括内部定义的函数或变量的。如果父组件需要调用子组件的方法或访问子组件的属性,就需要通过 expose() 明确声明暴露的内容。
一句话总结:expose() 函数允许你在 Vue 3 的组件中显式暴露方法或属性,供父组件使用。
基础语法
在使用 <script setup> 的组件中,直接调用 expose() 函数即可:
import { defineExpose } from 'vue'
const privateMethod = () => {
console.log('这是私有方法,不会被父组件访问')
}
const publicMethod = () => {
console.log('这是暴露给父组件的方法')
}
// 暴露 publicMethod 方法
defineExpose({
publicMethod
})
默认不暴露
如果不使用 expose(),组件中定义的函数和变量默认不会被暴露。例如:
const greet = () => {
console.log('你好,Vue 3')
}
父组件中通过 ref 获取该组件实例时,是无法调用 greet() 方法的。
用法一:暴露单个方法
import { defineExpose } from 'vue'
const sayHello = () => {
console.log('Hello from child component')
}
defineExpose({
sayHello
})
用法二:暴露多个属性和方法
import { defineExpose, ref } from 'vue'
const count = ref(0)
const increment = () => {
count.value++
}
defineExpose({
count,
increment
})
此时父组件可以通过 ref 调用 increment(),并读取 count 的值。
进阶特性
expose() 在 Vue 3 的 <script setup> 模式中非常关键,它提供了灵活控制组件 API 的能力。以下是一些常见的高级用法:
| 特性 | 说明 | 示例 |
|---|---|---|
| 选择性暴露 | 你可以选择暴露部分函数或属性,避免暴露不必要的内容 | defineExpose({ sayHello }) |
| 暴露响应式数据 | 可以暴露 ref、reactive 等响应式对象,父组件能响应变化 | defineExpose({ counter: count }) |
| 暴露计算属性 | 通过 expose 暴露 computed 属性,父组件可以访问并响应 | const age = computed(() => 2024 - birthYear.value); defineExpose({ age }) |
| 暴露自定义事件 | 父组件可以通过 ref.value.$emit() 调用子组件的事件 |
defineExpose({ triggerEvent }) |
示例:暴露计算属性
import { defineExpose, ref, computed } from 'vue'
const birthYear = ref(2000)
const age = computed(() => 2024 - birthYear.value) // 计算当前年龄
// 暴露 age 属性
defineExpose({
age
})
父组件通过 ref 可以访问 childComponent.age.value,并响应其变化。
实战应用
场景一:父组件调用子组件方法
假设子组件有一个 reset() 方法,需要在父组件中调用。
子组件(ChildComponent.vue)
<script setup>
import { defineExpose } from 'vue'
const reset = () => {
console.log('子组件的 reset 方法被调用')
}
defineExpose({
reset
})
</script>
父组件(ParentComponent.vue)
<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'
const childRef = ref()
const callChildReset = () => {
childRef.value.reset() // 调用子组件暴露的方法
}
</script>
<template>
<ChildComponent ref="childRef" />
<button @click="callChildReset">重置子组件</button>
</template>
场景二:暴露响应式数据供父组件读取
子组件
<script setup>
import { defineExpose, ref } from 'vue'
const counter = ref(0)
const increment = () => {
counter.value++
}
defineExpose({
counter
})
</script>
<template>
<p>当前计数:{{ counter }}</p>
<button @click="increment">+1</button>
</template>
父组件
<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'
const childRef = ref()
const showCounter = () => {
console.log('子组件计数器值:', childRef.value.counter.value)
}
</script>
<template>
<ChildComponent ref="childRef" />
<button @click="showCounter">显示子组件计数器</button>
</template>
注意事项
expose()只在<script setup>语法中使用,不能与setup()函数混用- 暴露的 API 不能是函数表达式,必须是命名函数或变量引用
- 不要暴露过多内部实现细节,暴露的 API 应保持简洁
- 不能暴露
props,因为 props 是只读的,且 Vue 会自动处理它们
总结
expose() 函数是 Vue 3 中用于控制组件对外 API 的关键工具,它让父组件能够访问子组件的特定方法和属性,是 <script setup> 语法下实现组件间通信的推荐方式。掌握它的使用,能提升组件的可维护性和封装性。