Skip to content

Commit 00978f7

Browse files
authored
fix(Teleport): hydrate disabled Teleport with undefined target (#11235)
close #11230
1 parent ef20b86 commit 00978f7

File tree

2 files changed

+52
-10
lines changed

2 files changed

+52
-10
lines changed

packages/runtime-core/__tests__/hydration.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2357,6 +2357,30 @@ describe('SSR hydration', () => {
23572357
expect(`Hydration style mismatch`).not.toHaveBeenWarned()
23582358
})
23592359

2360+
test('with disabled teleport + undefined target', async () => {
2361+
const container = document.createElement('div')
2362+
const isOpen = ref(false)
2363+
const App = {
2364+
setup() {
2365+
return { isOpen }
2366+
},
2367+
template: `
2368+
<Teleport :to="undefined" :disabled="true">
2369+
<div v-if="isOpen">
2370+
Menu is open...
2371+
</div>
2372+
</Teleport>`,
2373+
}
2374+
container.innerHTML = await renderToString(h(App))
2375+
const app = createSSRApp(App)
2376+
app.mount(container)
2377+
isOpen.value = true
2378+
await nextTick()
2379+
expect(container.innerHTML).toBe(
2380+
`<!--teleport start--><div> Menu is open... </div><!--teleport end-->`,
2381+
)
2382+
})
2383+
23602384
test('escape css var name', () => {
23612385
const container = document.createElement('div')
23622386
container.innerHTML = `<div style="padding: 4px;--foo\\.bar:red;"></div>`

packages/runtime-core/src/components/Teleport.ts

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -406,29 +406,43 @@ function hydrateTeleport(
406406
optimized: boolean,
407407
) => Node | null,
408408
): Node | null {
409+
function hydrateDisabledTeleport(
410+
node: Node,
411+
vnode: VNode,
412+
targetStart: Node | null,
413+
targetAnchor: Node | null,
414+
) {
415+
vnode.anchor = hydrateChildren(
416+
nextSibling(node),
417+
vnode,
418+
parentNode(node)!,
419+
parentComponent,
420+
parentSuspense,
421+
slotScopeIds,
422+
optimized,
423+
)
424+
vnode.targetStart = targetStart
425+
vnode.targetAnchor = targetAnchor
426+
}
427+
409428
const target = (vnode.target = resolveTarget<Element>(
410429
vnode.props,
411430
querySelector,
412431
))
432+
const disabled = isTeleportDisabled(vnode.props)
413433
if (target) {
414-
const disabled = isTeleportDisabled(vnode.props)
415434
// if multiple teleports rendered to the same target element, we need to
416435
// pick up from where the last teleport finished instead of the first node
417436
const targetNode =
418437
(target as TeleportTargetElement)._lpa || target.firstChild
419438
if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
420439
if (disabled) {
421-
vnode.anchor = hydrateChildren(
422-
nextSibling(node),
440+
hydrateDisabledTeleport(
441+
node,
423442
vnode,
424-
parentNode(node)!,
425-
parentComponent,
426-
parentSuspense,
427-
slotScopeIds,
428-
optimized,
443+
targetNode,
444+
targetNode && nextSibling(targetNode),
429445
)
430-
vnode.targetStart = targetNode
431-
vnode.targetAnchor = targetNode && nextSibling(targetNode)
432446
} else {
433447
vnode.anchor = nextSibling(node)
434448

@@ -470,6 +484,10 @@ function hydrateTeleport(
470484
}
471485
}
472486
updateCssVars(vnode, disabled)
487+
} else if (disabled) {
488+
if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
489+
hydrateDisabledTeleport(node, vnode, node, nextSibling(node))
490+
}
473491
}
474492
return vnode.anchor && nextSibling(vnode.anchor as Node)
475493
}

0 commit comments

Comments
 (0)