From 85693f0eb34d4e2c7aa088064c9dea74fb8bbf88 Mon Sep 17 00:00:00 2001 From: daiwei Date: Wed, 30 Jul 2025 14:39:56 +0800 Subject: [PATCH] feat(hydration): handle consecutive if node --- .../runtime-vapor/__tests__/hydration.spec.ts | 20 +++++++++++++++++++ packages/runtime-vapor/src/block.ts | 10 ++++++++-- packages/runtime-vapor/src/dom/hydration.ts | 16 +++++++++------ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/packages/runtime-vapor/__tests__/hydration.spec.ts b/packages/runtime-vapor/__tests__/hydration.spec.ts index ffe2e8f098..5aba438ded 100644 --- a/packages/runtime-vapor/__tests__/hydration.spec.ts +++ b/packages/runtime-vapor/__tests__/hydration.spec.ts @@ -1269,6 +1269,26 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe(``) }) + test('consecutive if node', async () => { + const data = ref(true) + const { container } = await testHydration( + ``, + { Child: `` }, + data, + ) + expect(container.innerHTML).toBe(`
foo
`) + + data.value = false + await nextTick() + expect(container.innerHTML).toBe(``) + + data.value = true + await nextTick() + expect(container.innerHTML).toBe(`
foo
`) + }) + test('v-if/else-if/else chain on component - switch branches', async () => { const data = ref('a') const { container } = await testHydration( diff --git a/packages/runtime-vapor/src/block.ts b/packages/runtime-vapor/src/block.ts index dc6ae46665..c1be8202ae 100644 --- a/packages/runtime-vapor/src/block.ts +++ b/packages/runtime-vapor/src/block.ts @@ -8,6 +8,7 @@ import { import { createComment, createTextNode } from './dom/node' import { EffectScope, setActiveSub } from '@vue/reactivity' import { + advanceHydrationNode, currentHydrationNode, isComment, isHydrating, @@ -41,12 +42,13 @@ export class DynamicFragment extends VaporFragment { current?: BlockFn fallback?: BlockFn teardown?: () => void + anchorLabel?: string constructor(anchorLabel?: string) { super([]) if (isHydrating) { + this.anchorLabel = anchorLabel locateHydrationNode() - this.hydrate(anchorLabel!) } else { this.anchor = __DEV__ && anchorLabel ? createComment(anchorLabel) : createTextNode() @@ -55,12 +57,13 @@ export class DynamicFragment extends VaporFragment { update(render?: BlockFn, key: any = render): void { if (key === this.current) { + if (isHydrating) this.hydrate(this.anchorLabel!) return } this.current = key const prevSub = setActiveSub() - const parent = this.anchor.parentNode + const parent = isHydrating ? null : this.anchor.parentNode // teardown previous branch if (this.scope) { @@ -89,6 +92,8 @@ export class DynamicFragment extends VaporFragment { } setActiveSub(prevSub) + + if (isHydrating) this.hydrate(this.anchorLabel!) } hydrate(label: string): void { @@ -105,6 +110,7 @@ export class DynamicFragment extends VaporFragment { throw new Error(`${label} fragment anchor node was not found.`) } } + advanceHydrationNode(this.anchor) } } diff --git a/packages/runtime-vapor/src/dom/hydration.ts b/packages/runtime-vapor/src/dom/hydration.ts index 6730f1e57f..1e12a07197 100644 --- a/packages/runtime-vapor/src/dom/hydration.ts +++ b/packages/runtime-vapor/src/dom/hydration.ts @@ -19,6 +19,10 @@ export function setCurrentHydrationNode(node: Node | null): void { currentHydrationNode = node } +export function advanceHydrationNode(node: Node): void { + setCurrentHydrationNode(node.nextSibling || node.parentNode) +} + let isOptimized = false function performHydration( @@ -96,7 +100,7 @@ function adoptTemplateImpl(node: Node, template: string): Node | null { } } - currentHydrationNode = node.nextSibling + advanceHydrationNode(node) return node } @@ -169,12 +173,12 @@ export function isNonHydrationNode(node: Node): boolean { export function locateVaporFragmentAnchor( node: Node, anchorLabel: string, -): Comment | undefined { - let n = node.nextSibling - while (n) { - if (isComment(n, anchorLabel)) return n - n = n.nextSibling +): Comment | null { + while (node) { + if (isComment(node, anchorLabel)) return node + node = node.nextSibling! } + return null } export function isEmptyTextNode(node: Node): node is Text { -- 2.47.2