fix(compiler-ssr): fix hydration mismatch for conditional slot in transition
close #10743
This commit is contained in:
parent
c8e87a1c90
commit
f12c81efca
|
@ -102,6 +102,9 @@ export interface TransformContext
|
||||||
vOnce: number
|
vOnce: number
|
||||||
}
|
}
|
||||||
parent: ParentNode | null
|
parent: ParentNode | null
|
||||||
|
// we could use a stack but in practice we've only ever needed two layers up
|
||||||
|
// so this is more efficient
|
||||||
|
grandParent: ParentNode | null
|
||||||
childIndex: number
|
childIndex: number
|
||||||
currentNode: RootNode | TemplateChildNode | null
|
currentNode: RootNode | TemplateChildNode | null
|
||||||
inVOnce: boolean
|
inVOnce: boolean
|
||||||
|
@ -193,6 +196,7 @@ export function createTransformContext(
|
||||||
vOnce: 0,
|
vOnce: 0,
|
||||||
},
|
},
|
||||||
parent: null,
|
parent: null,
|
||||||
|
grandParent: null,
|
||||||
currentNode: root,
|
currentNode: root,
|
||||||
childIndex: 0,
|
childIndex: 0,
|
||||||
inVOnce: false,
|
inVOnce: false,
|
||||||
|
@ -401,6 +405,7 @@ export function traverseChildren(
|
||||||
for (; i < parent.children.length; i++) {
|
for (; i < parent.children.length; i++) {
|
||||||
const child = parent.children[i]
|
const child = parent.children[i]
|
||||||
if (isString(child)) continue
|
if (isString(child)) continue
|
||||||
|
context.grandParent = context.parent
|
||||||
context.parent = parent
|
context.parent = parent
|
||||||
context.childIndex = i
|
context.childIndex = i
|
||||||
context.onNodeRemoved = nodeRemoved
|
context.onNodeRemoved = nodeRemoved
|
||||||
|
|
|
@ -143,4 +143,20 @@ describe('ssr: <slot>', () => {
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('with v-if inside transition', () => {
|
||||||
|
const { code } = compile(`<transition><slot v-if="true"/></transition>`)
|
||||||
|
expect(code).toMatch(ssrHelpers[SSR_RENDER_SLOT_INNER])
|
||||||
|
expect(code).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderSlotInner: _ssrRenderSlotInner } = require("vue/server-renderer")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
if (true) {
|
||||||
|
_ssrRenderSlotInner(_ctx.$slots, "default", {}, null, _push, _parent, null, true)
|
||||||
|
} else {
|
||||||
|
_push(\`<!---->\`)
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -40,24 +40,30 @@ export const ssrTransformSlotOutlet: NodeTransform = (node, context) => {
|
||||||
|
|
||||||
// #3989, #9933
|
// #3989, #9933
|
||||||
// check if this is a single slot inside a transition wrapper - since
|
// check if this is a single slot inside a transition wrapper - since
|
||||||
// transition/transition-group will unwrap the slot fragment into vnode(s) at runtime,
|
// transition/transition-group will unwrap the slot fragment into vnode(s)
|
||||||
// we need to avoid rendering the slot as a fragment.
|
// at runtime, we need to avoid rendering the slot as a fragment.
|
||||||
const parent = context.parent
|
let parent = context.parent!
|
||||||
let componentType
|
if (parent) {
|
||||||
if (
|
const children = parent.children
|
||||||
parent &&
|
// #10743 <slot v-if> in <Transition>
|
||||||
parent.type === NodeTypes.ELEMENT &&
|
if (parent.type === NodeTypes.IF_BRANCH) {
|
||||||
parent.tagType === ElementTypes.COMPONENT &&
|
parent = context.grandParent!
|
||||||
((componentType = resolveComponentType(parent, context, true)) ===
|
}
|
||||||
TRANSITION ||
|
let componentType
|
||||||
componentType === TRANSITION_GROUP) &&
|
if (
|
||||||
parent.children.filter(c => c.type === NodeTypes.ELEMENT).length === 1
|
parent.type === NodeTypes.ELEMENT &&
|
||||||
) {
|
parent.tagType === ElementTypes.COMPONENT &&
|
||||||
method = SSR_RENDER_SLOT_INNER
|
((componentType = resolveComponentType(parent, context, true)) ===
|
||||||
if (!(context.scopeId && context.slotted !== false)) {
|
TRANSITION ||
|
||||||
args.push('null')
|
componentType === TRANSITION_GROUP) &&
|
||||||
|
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')
|
||||||
}
|
}
|
||||||
args.push('true')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node.ssrCodegenNode = createCallExpression(context.helper(method), args)
|
node.ssrCodegenNode = createCallExpression(context.helper(method), args)
|
||||||
|
|
Loading…
Reference in New Issue