Skip to content

Commit cb629e4

Browse files
linzhe1419romise
authored andcommitted
fix(Teleport): hydrate disabled Teleport with undefined target (#11235)
close #11230
1 parent f9d69e0 commit cb629e4

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
@@ -419,29 +419,43 @@ function hydrateTeleport(
419419
optimized: boolean,
420420
) => Node | null,
421421
): Node | null {
422+
function hydrateDisabledTeleport(
423+
node: Node,
424+
vnode: VNode,
425+
targetStart: Node | null,
426+
targetAnchor: Node | null,
427+
) {
428+
vnode.anchor = hydrateChildren(
429+
nextSibling(node),
430+
vnode,
431+
parentNode(node)!,
432+
parentComponent,
433+
parentSuspense,
434+
slotScopeIds,
435+
optimized,
436+
)
437+
vnode.targetStart = targetStart
438+
vnode.targetAnchor = targetAnchor
439+
}
440+
422441
const target = (vnode.target = resolveTarget<Element>(
423442
vnode.props,
424443
querySelector,
425444
))
445+
const disabled = isTeleportDisabled(vnode.props)
426446
if (target) {
427-
const disabled = isTeleportDisabled(vnode.props)
428447
// if multiple teleports rendered to the same target element, we need to
429448
// pick up from where the last teleport finished instead of the first node
430449
const targetNode =
431450
(target as TeleportTargetElement)._lpa || target.firstChild
432451
if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
433452
if (disabled) {
434-
vnode.anchor = hydrateChildren(
435-
nextSibling(node),
453+
hydrateDisabledTeleport(
454+
node,
436455
vnode,
437-
parentNode(node)!,
438-
parentComponent,
439-
parentSuspense,
440-
slotScopeIds,
441-
optimized,
456+
targetNode,
457+
targetNode && nextSibling(targetNode),
442458
)
443-
vnode.targetStart = targetNode
444-
vnode.targetAnchor = targetNode && nextSibling(targetNode)
445459
} else {
446460
vnode.anchor = nextSibling(node)
447461

@@ -483,6 +497,10 @@ function hydrateTeleport(
483497
}
484498
}
485499
updateCssVars(vnode, disabled)
500+
} else if (disabled) {
501+
if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
502+
hydrateDisabledTeleport(node, vnode, node, nextSibling(node))
503+
}
486504
}
487505
return vnode.anchor && nextSibling(vnode.anchor as Node)
488506
}

0 commit comments

Comments
 (0)