Vue:忽略已定义插槽的插槽包装器

3
Vue对象有一个非常有用的成员,叫做$attrs$attrs包含当前组件中未被识别为props的所有属性。一个很好的$attrs示例在这里
我想知道是否有一个类似于$attrs$scopedSlots等效物。目前,我正在使用类似于https://dev59.com/AFUL5IYBdhLWcg3wFElR#50892881建议的方法。问题在于$scopedSlots也传递了已定义的插槽。在这里使用该示例:

<template>
    <wrapper>
      <b-table :foo="foo" v-bind="$attrs" v-on="$listeners">
        <template v-for="(_, slot) of $scopedSlots" v-slot:[slot]="scope"><slot :name="slot" v-bind="scope"/></template>
      </b-table>
      <slot name="mySlot"></slot>
    </wrapper>
</template>

<script>
export default {
    props: {
        // let's pretend that `b-table` has a prop `foo` that is default `false`
        foo: {
            type: boolean,
            default: true,
        }
    }
}
</script>

现在,由于$attrs的行为,foo将不会被绑定两次,但mySlot将被发送到wrapper和b-table。那么我如何传递除了我自己定义的之外的所有插槽呢?我的一个想法是:
computed: {
   bTableSlots() {
       Object.keys(this.$scopedSlots)
          .filter( key => key!=='mySlot' )
          .reduce( (res, key) => (res[key] = this.$scopedSlots[key], res), {} );
    }
}

然后

        <template v-for="(_, slot) of bTableSlots" v-slot:[slot]="scope"><slot :name="slot" v-bind="scope"/></template>

我在想是否有更好的方法来做这件事。谢谢!

1个回答

1

那么如何传递除了我自己定义的之外的所有插槽呢?

为什么这会成为问题呢?如果 <b-table> 没有名为 mySlot 的命名插槽,它将忽略它 - 最终它只是在其 $scopedSlots 属性中多了一个条目,组件永远不会访问它。并且由于作用域插槽被传递为函数,因此您不需要支付任何额外的费用。

当 Vue 编译器看到插槽的内容(<template #slotName>)时,它将获取内容并将其编译为 VNode 数组或返回 VNode 数组的函数,并将其向下传递给子组件。事实上,您的子组件进一步传递它并不会产生任何额外的成本。它是对现有数组的引用或对现有函数的引用(对于作用域插槽),在两种情况下,如果更深层次的组件不知道具有完全相同名称的插槽,则除了在 $scopedSlots 中多了一个条目之外,没有任何额外的成本...

如果您觉得这是个问题,我恐怕筛选是唯一的方法——您可以按照自己的方式或使用一些辅助数组[ 'slot1', 'slot2' ]来定义所有现有的b-table插槽并过滤其他所有内容(我认为这并不更好,因为每次b-table添加新插槽时都需要更新组件)....
我理解这个想法,并看到与$attrs的相似之处——可能会在组件上有一个类似于$unknownSlots的东西来保存当前组件未定义的插槽,但Vue公共API中目前没有这样的东西...

我更担心性能问题而不是命名冲突。你的意思是说,由于$scopedSlots是一个以name为键的对象,如果我向其中添加一个未使用的条目,它将对性能影响很小?如果是这样,那么这是一个可以接受的解决方案。 - Max Coplan
如果您添加了“未使用”的插槽,价格将是编译时间(构建时)以及JS引擎解析传递给插槽的渲染函数所需的内存和时间。但是,如果您传递“mySlot”,则创建的函数将由您的组件使用(不浪费)。事实上,该函数还传递到“b-table”$scopedSlots中是无关紧要的...它是相同的函数。 - Michal Levý
@MaxCoplan 我在之前的回答中加入了关于性能的重点。希望现在更清晰了... - Michal Levý

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接