fix(ssr): hydration for transition wrapper components with empty slot content (#5995)
fix #5991
This commit is contained in:
parent
0cf9ae62be
commit
eb22a62798
@ -123,7 +123,7 @@ describe('ssr: <slot>', () => {
|
|||||||
"const { ssrRenderSlotInner: _ssrRenderSlotInner } = require(\\"vue/server-renderer\\")
|
"const { ssrRenderSlotInner: _ssrRenderSlotInner } = require(\\"vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_ssrRenderSlotInner(_ctx.$slots, \\"default\\", {}, null, _push, _parent)
|
_ssrRenderSlotInner(_ctx.$slots, \\"default\\", {}, null, _push, _parent, null, true)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
@ -50,6 +50,10 @@ export const ssrTransformSlotOutlet: NodeTransform = (node, context) => {
|
|||||||
parent.children.filter(c => c.type === NodeTypes.ELEMENT).length === 1
|
parent.children.filter(c => c.type === NodeTypes.ELEMENT).length === 1
|
||||||
) {
|
) {
|
||||||
method = SSR_RENDER_SLOT_INNER
|
method = SSR_RENDER_SLOT_INNER
|
||||||
|
if (!(context.scopeId && context.slotted !== false)) {
|
||||||
|
args.push('null')
|
||||||
|
}
|
||||||
|
args.push('true')
|
||||||
}
|
}
|
||||||
|
|
||||||
node.ssrCodegenNode = createCallExpression(context.helper(method), args)
|
node.ssrCodegenNode = createCallExpression(context.helper(method), args)
|
||||||
|
@ -113,4 +113,32 @@ describe('ssr: slot', () => {
|
|||||||
`<div><!--[--><!--[--><div>one</div><div>two</div><!--]--><!--]--></div>`
|
`<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>`)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -40,7 +40,8 @@ export function ssrRenderSlotInner(
|
|||||||
fallbackRenderFn: (() => void) | null,
|
fallbackRenderFn: (() => void) | null,
|
||||||
push: PushFn,
|
push: PushFn,
|
||||||
parentComponent: ComponentInternalInstance,
|
parentComponent: ComponentInternalInstance,
|
||||||
slotScopeId?: string
|
slotScopeId?: string,
|
||||||
|
transition?: boolean
|
||||||
) {
|
) {
|
||||||
const slotFn = slots[slotName]
|
const slotFn = slots[slotName]
|
||||||
if (slotFn) {
|
if (slotFn) {
|
||||||
@ -61,10 +62,14 @@ export function ssrRenderSlotInner(
|
|||||||
// ssr slot.
|
// ssr slot.
|
||||||
// check if the slot renders all comments, in which case use the fallback
|
// check if the slot renders all comments, in which case use the fallback
|
||||||
let isEmptySlot = true
|
let isEmptySlot = true
|
||||||
for (let i = 0; i < slotBuffer.length; i++) {
|
if (transition) {
|
||||||
if (!isComment(slotBuffer[i])) {
|
isEmptySlot = false
|
||||||
isEmptySlot = false
|
} else {
|
||||||
break
|
for (let i = 0; i < slotBuffer.length; i++) {
|
||||||
|
if (!isComment(slotBuffer[i])) {
|
||||||
|
isEmptySlot = false
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isEmptySlot) {
|
if (isEmptySlot) {
|
||||||
|
Loading…
Reference in New Issue
Block a user