I am currently migrating a Vue 2 codebase to Vue 3.
<card>
<template #default>
<card-header>
<title level="3">Header</title>
</card-header>
<card-body
v-for="b in bodyCount"
:key="'b' + b">
Body {{ b }}
</card-body>
<card-footer
v-for="f in footerCount"
:key="'f' + f">
<text>Footer {{ f }}</text>
</card-footer>
</template>
</card>
Card component has a render function which calls this.$slots.default()
. However in Vue 3 this returns different content to what it did in Vue 2. So if I do console.log(this.$slots.default())
- I get an array with 3 elements, [v-node with type: 'header', v-node with type: Symbol(Fragment), v-node with type: Symbol(Fragment)]
More specifically it does not identify card-footer/card-body as components but rather I see Symbol (Fragment) in the type. Card-header is actually fine because it is not in a v-for loop.
There is logic inside the render function of the card component which needs to know how many body/footer components it has. So I need to be able to tell the component types. Is this not possible in Vue 3? I can guess that this is related to the v-for here but I am not sure how to actually get the end result v-nodes. In this example I would have expected the array to contain the card-header + all card bodies + all card footers instead of 3 elements.
As it turns out - Fragments can be unwrapped through the children property on each element of the array. So v-for in this case results in a v-node which is a fragment but we can infer further content by looking at the children property.