composition-api
composition-api copied to clipboard
`context.slots` is not mirrored from `$slots` or `$scopedSlots` currectly after setup. Is it needed to run `resolveScopedSlots` again after each updated lifecycle to sync the `context.slots`?
I use a wrapper components, which contains a <slots />
element to allow another component rendered inside. Once the slots element was shown after the setup process, I found the content of context.slots
of wrapper component doesn't mirrored from $scopedSlots
or $slots
.
I found another issue about this problem, #911. Here is a test case to explain the situation:
it('should synchronously update context.slots after each render', async () => {
let context: SetupContext = undefined!
const Wrapper = defineComponent({
setup(_, ctx) {
context = ctx
},
template: `<div><slot /></div>`,
})
const Foo = defineComponent({
components: {
Wrapper,
},
setup() {
const showDiv = ref(false)
return {
showDiv,
}
},
template: `<wrapper><div v-if="showDiv"></div></wrapper>`,
})
const vm = createApp(Foo).mount()
await nextTick()
//@ts-ignore
vm.showDiv = true
await nextTick()
//@ts-ignore
expect(context.slots.default).toBeDefined()
})
It runs failed due to the undefined of the slots.default
.
I try to figure out this problem, and found that adding resolveScopedSlots
func intoafterRender
(src/utils/instance.ts
) can make the context.slots synchronized context.slots
and actual slot content, like:
export function afterRender(vm: ComponentInstance) {
+ const attrs = vmStateManager.get(vm, 'attrBindings')
+ if (attrs?.ctx.slots) {
+ resolveScopedSlots(vm, attrs.ctx.slots)
+ }
const stack = [(vm as any)._vnode as VNode]
while (stack.length) {
const vnode = stack.pop()
if (vnode) {
if (vnode.context) updateTemplateRef(vnode.context)
if (vnode.children) {
for (let i = 0; i < vnode.children.length; ++i) {
stack.push(vnode.children[i])
}
}
}
}
}
But I don't think this is the best practice to solve the problem because the method to get the setupContext is a bit of a hook.
Is it any ideas to solve it?
Stale issue message
Solve it?