Reputation: 1503
The Vue object has a really helpful member called $attrs
. What $attrs does is contain all the attributes that aren't recognized as props for the current component. A good example of $attrs
is here.
I am wondering if there is an equivalent for $attrs
for $scopedSlots
. I am currently using an approach similar to the first suggestion from https://stackoverflow.com/a/50892881/6100005 . The issue with $scopedSlots
is it also passes already-defined slots. To use that example here:
<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>
Now, foo
will not get binded twice, thanks to the behavior of $attrs
, but mySlot
will be sent to both wrapper
and b-table
.
So how can pass I down all the slots except for the one I'm defining myself?
One idea I have is to have
computed: {
bTableSlots() {
Object.keys(this.$scopedSlots)
.filter( key => key!=='mySlot' )
.reduce( (res, key) => (res[key] = this.$scopedSlots[key], res), {} );
}
}
And then
<template v-for="(_, slot) of bTableSlots" v-slot:[slot]="scope"><slot :name="slot" v-bind="scope"/></template>
Was wondering if there were a better way to do this. Thanks!
Upvotes: 3
Views: 767
Reputation: 37953
So how can pass down all the slots except for the one I'm defining myself?
Why is this even a problem ? If the <b-table>
doesn't have named slot with name mySlot
, it will just ignore it - in the end it's just one more entry in it's $scopedSlots
property the component will never access. And because the scoped slots are passed as a functions, you are not paying any additional price.
When Vue compiler sees the content of the slot (<template #slotName>
), it will take the content and compile it into Array
of VNode
s or function returning Array
of VNode
s and pass it down to a child component. The fact your child component pass it down even further does not incur any additional cost. It's a reference to an existing array or a reference to an existing function (for scoped slots) and in both cases if the component further down doesn't know about the slot with exact same name, there is no additional cost except there is one more entry in $scopedSlots
...
If you feel it's a problem I'm afraid filtering is only way to go - you can do it your way or by some helper array [ 'slot1', 'slot2' ]
defining all existing b-table
slots and filtering everything else (not better imho as you need to update component every time b-table
adds new slot)....
I understand the idea and see the similarity with $attrs
- there could be something as $unknownSlots
on component to hold the slots not defined by the current component but there is nothing like this in Vue public API right now...
Upvotes: 1