插槽(父组件中)中有一些组件(子组件),我想调用它们的方法。我尝试了以下步骤:
useSlots
defineExpose
但是,该方法并未按预期出现在对象上。
示例:
// Parent.vue
<template>
<div><slot/></div>
</template>
<script lang="ts" setup>
const slots = useSlots() as any;
const children = slots.default();
function callMethods() {
console.log(children);
}
</script>
// SomeComponent.vue
<template>
// ...
</template>
<script lang="ts" setup>
// ...
function methodToBeCalledByParent() {
console.log(123);
}
defineExpose({
methodToBeCalledByParent
});
</script>
在除上述两个之外的某个地方,我放置了以下代码:
<parent>
<some-component/>
<some-component/>
</parent>
目标:让
callMethods
能够通过methodToBeCalledByParent
对象分别调用some-component
中的children
。
当调用
callMethods
时,控制台中应该打印两个 some-component
的数组。虽然数字是正确的,并且组件的基本结构也存在,但每个子项的内容似乎都不正确。有这么多null
(也许这是预料之中的?),最重要的是,在对象中找不到暴露的methodToBeCalledByParent
。
我在网上查了一下,发现只要获取到组件对象就可以直接调用该方法。所以我很困惑。我的代码一定有问题。谁能告诉我正确的(或更好的)方法来做到这一点?
组件实例可能在 vnode 对象上可用,但这是内部数据,不应在生产中使用。
这需要将模板引用从插槽添加到 vnodes,这可以在渲染函数中完成:
setup() {
const slots = useSlots();
const slotRefs = reactive([]);
return () => {
const vnodes = slots.default?.();
if (!vnodes)
return null;
slotRefs.length = vnodes.length;
return vnodes.map((vnode, index) =>
cloneVNode(vnode, { ref: (el) => slotRefs[index] = el })
)
}
}
该方法类似于 React,其中借用了 Vue 渲染函数的概念。