如何使用 Vue 3 Composition API 调用槽中组件公开的方法

问题描述 投票:0回答:1

插槽(父组件中)中有一些组件(子组件),我想调用它们的方法。我尝试了以下步骤:

  • 使用
    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

output

我在网上查了一下,发现只要获取到组件对象就可以直接调用该方法。所以我很困惑。我的代码一定有问题。谁能告诉我正确的(或更好的)方法来做到这一点?

typescript vue.js vuejs3 vue-component vue-composition-api
1个回答
0
投票

组件实例可能在 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 渲染函数的概念。

© www.soinside.com 2019 - 2024. All rights reserved.