diff --git a/packages/runtime-core/__tests__/hydration.spec.ts b/packages/runtime-core/__tests__/hydration.spec.ts index 56011d063..2cd306817 100644 --- a/packages/runtime-core/__tests__/hydration.spec.ts +++ b/packages/runtime-core/__tests__/hydration.spec.ts @@ -2185,6 +2185,30 @@ describe('SSR hydration', () => { expect(`Hydration style mismatch`).not.toHaveBeenWarned() }) + test('with disabled teleport + undefined target', async () => { + const container = document.createElement('div') + const isOpen = ref(false) + const App = { + setup() { + return { isOpen } + }, + template: ` + +
+ Menu is open... +
+
`, + } + container.innerHTML = await renderToString(h(App)) + const app = createSSRApp(App) + app.mount(container) + isOpen.value = true + await nextTick() + expect(container.innerHTML).toBe( + `
Menu is open...
`, + ) + }) + test('escape css var name', () => { const container = document.createElement('div') container.innerHTML = `
` diff --git a/packages/runtime-core/src/components/Teleport.ts b/packages/runtime-core/src/components/Teleport.ts index fc2ee4c08..21e512618 100644 --- a/packages/runtime-core/src/components/Teleport.ts +++ b/packages/runtime-core/src/components/Teleport.ts @@ -406,29 +406,43 @@ function hydrateTeleport( optimized: boolean, ) => Node | null, ): Node | null { + function hydrateDisabledTeleport( + node: Node, + vnode: VNode, + targetStart: Node | null, + targetAnchor: Node | null, + ) { + vnode.anchor = hydrateChildren( + nextSibling(node), + vnode, + parentNode(node)!, + parentComponent, + parentSuspense, + slotScopeIds, + optimized, + ) + vnode.targetStart = targetStart + vnode.targetAnchor = targetAnchor + } + const target = (vnode.target = resolveTarget( vnode.props, querySelector, )) + const disabled = isTeleportDisabled(vnode.props) if (target) { - const disabled = isTeleportDisabled(vnode.props) // if multiple teleports rendered to the same target element, we need to // pick up from where the last teleport finished instead of the first node const targetNode = (target as TeleportTargetElement)._lpa || target.firstChild if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) { if (disabled) { - vnode.anchor = hydrateChildren( - nextSibling(node), + hydrateDisabledTeleport( + node, vnode, - parentNode(node)!, - parentComponent, - parentSuspense, - slotScopeIds, - optimized, + targetNode, + targetNode && nextSibling(targetNode), ) - vnode.targetStart = targetNode - vnode.targetAnchor = targetNode && nextSibling(targetNode) } else { vnode.anchor = nextSibling(node) @@ -470,6 +484,10 @@ function hydrateTeleport( } } updateCssVars(vnode, disabled) + } else if (disabled) { + if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) { + hydrateDisabledTeleport(node, vnode, node, nextSibling(node)) + } } return vnode.anchor && nextSibling(vnode.anchor as Node) }