fix(ssr): hydration for transition wrapper components with empty slot content (#5995)

fix #5991
This commit is contained in:
小刘(liulinboyi) 2022-06-06 16:24:40 +08:00 committed by GitHub
parent 0cf9ae62be
commit eb22a62798
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 6 deletions

View File

@ -123,7 +123,7 @@ describe('ssr: <slot>', () => {
"const { ssrRenderSlotInner: _ssrRenderSlotInner } = require(\\"vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent, _attrs) {
_ssrRenderSlotInner(_ctx.$slots, \\"default\\", {}, null, _push, _parent)
_ssrRenderSlotInner(_ctx.$slots, \\"default\\", {}, null, _push, _parent, null, true)
}"
`)
})

View File

@ -50,6 +50,10 @@ export const ssrTransformSlotOutlet: NodeTransform = (node, context) => {
parent.children.filter(c => c.type === NodeTypes.ELEMENT).length === 1
) {
method = SSR_RENDER_SLOT_INNER
if (!(context.scopeId && context.slotted !== false)) {
args.push('null')
}
args.push('true')
}
node.ssrCodegenNode = createCallExpression(context.helper(method), args)

View File

@ -113,4 +113,32 @@ describe('ssr: slot', () => {
`<div><!--[--><!--[--><div>one</div><div>two</div><!--]--><!--]--></div>`
)
})
test('transition slot', async () => {
expect(
await renderToString(
createApp({
components: {
one: {
template: `<transition><slot/></transition>`
}
},
template: `<one><div v-if="false">foo</div></one>`
})
)
).toBe(`<!---->`)
expect(
await renderToString(
createApp({
components: {
one: {
template: `<transition><slot/></transition>`
}
},
template: `<one><div v-if="true">foo</div></one>`
})
)
).toBe(`<div>foo</div>`)
})
})

View File

@ -40,7 +40,8 @@ export function ssrRenderSlotInner(
fallbackRenderFn: (() => void) | null,
push: PushFn,
parentComponent: ComponentInternalInstance,
slotScopeId?: string
slotScopeId?: string,
transition?: boolean
) {
const slotFn = slots[slotName]
if (slotFn) {
@ -61,10 +62,14 @@ export function ssrRenderSlotInner(
// ssr slot.
// check if the slot renders all comments, in which case use the fallback
let isEmptySlot = true
for (let i = 0; i < slotBuffer.length; i++) {
if (!isComment(slotBuffer[i])) {
isEmptySlot = false
break
if (transition) {
isEmptySlot = false
} else {
for (let i = 0; i < slotBuffer.length; i++) {
if (!isComment(slotBuffer[i])) {
isEmptySlot = false
break
}
}
}
if (isEmptySlot) {