需求:vue3中使用defineExpose+ref调用子组件方法报错不是一个function
思路:由于组件嵌套层级太深导致ref失效,通过provide/inject + 回调函数来实现多层穿透
1. 父组件提供「方法注册函数」
父组件通过 provide
提供一个用于接收子组件方法的函数:
<!-- 父组件 Parent.vue -->
<template>
<div>
<!-- 深层嵌套的子组件 -->
<div>
<div>
<ChildComponent />
</div>
</div>
<a-button @click="callChildMethod">调用子组件方法</a-button>
</div>
</template>
<script setup>
import { provide, ref } from 'vue';
// 存储子组件方法的引用
const childMethod = ref(null);
// 提供注册方法给子组件
provide('registerChildMethod', (method) => {
childMethod.value = method;
});
// 调用子组件方法
const callChildMethod = async () => {
if (childMethod.value) {
try {
await childMethod.value();
console.log('子组件方法调用成功');
} catch (error) {
console.error('调用失败:', error);
}
}
};
</script>
2. 子组件注入并注册方法
子组件通过 inject
获取注册函数,将自己的方法传递给父组件:
<!-- 子组件 ChildComponent.vue -->
<template>
<a-form ref="formRef" :model="formState">
<a-form-item label="名称" name="name" :rules="[{ required: true }]">
<a-input v-model:value="formState.name" />
</a-form-item>
</a-form>
</template>
<script setup>
import { inject, ref, onMounted, onUnmounted } from 'vue';
// 子组件方法:表单验证
const formRef = ref(null);
const validateForm = () => formRef.value.validate();
// 注入父组件的注册函数
const registerChildMethod = inject('registerChildMethod');
// 组件挂载时注册方法
onMounted(() => {
if (registerChildMethod) {
registerChildMethod(validateForm); // 将方法传递给父组件
}
});
onUnmounted(() => {
if (registerChildMethod) {
registerChildMethod(null); // 清除引用
}
});
</script>