From: daiwei Date: Wed, 23 Apr 2025 09:07:38 +0000 (+0800) Subject: chore: dont process text/comment node as dynamic X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3e7f093519d6459aac2951dedd3fb6048b583d60;p=thirdparty%2Fvuejs%2Fcore.git chore: dont process text/comment node as dynamic --- diff --git a/packages/compiler-ssr/src/ssrCodegenTransform.ts b/packages/compiler-ssr/src/ssrCodegenTransform.ts index c56dea164c..85118d91b3 100644 --- a/packages/compiler-ssr/src/ssrCodegenTransform.ts +++ b/packages/compiler-ssr/src/ssrCodegenTransform.ts @@ -269,8 +269,10 @@ export function processChildrenAsStatement( return createBlockStatement(childContext.body) } -const isStaticElement = (c: TemplateChildNode): boolean => - c.type === NodeTypes.ELEMENT && c.tagType !== ElementTypes.COMPONENT +const isStaticChildNode = (c: TemplateChildNode): boolean => + (c.type === NodeTypes.ELEMENT && c.tagType !== ElementTypes.COMPONENT) || + c.type === NodeTypes.TEXT || + c.type === NodeTypes.COMMENT /** * Check if a node should be processed as dynamic. @@ -289,11 +291,13 @@ function shouldProcessAsDynamic( node: TemplateChildNode, ): boolean { // 1. Must be a dynamic node type - if (isStaticElement(node)) return false + if (isStaticChildNode(node)) return false // 2. Must be inside a parent element if (!parent.tag) return false - const children = parent.children + const children = parent.children.filter( + child => !(child.type === NodeTypes.TEXT && !child.content.trim()), + ) const len = children.length const index = children.indexOf(node) @@ -301,7 +305,7 @@ function shouldProcessAsDynamic( let hasStaticPreviousSibling = false if (index > 0) { for (let i = index - 1; i >= 0; i--) { - if (isStaticElement(children[i])) { + if (isStaticChildNode(children[i])) { hasStaticPreviousSibling = true break } @@ -313,7 +317,7 @@ function shouldProcessAsDynamic( let hasStaticNextSibling = false if (index > -1 && index < len - 1) { for (let i = index + 1; i < len; i++) { - if (isStaticElement(children[i])) { + if (isStaticChildNode(children[i])) { hasStaticNextSibling = true break } @@ -321,19 +325,39 @@ function shouldProcessAsDynamic( } if (!hasStaticNextSibling) return false - // 5. Check for a consecutive dynamic sibling (immediately before or after) - let hasConsecutiveDynamicNodes = false - if (index > 0 && !isStaticElement(children[index - 1])) { - hasConsecutiveDynamicNodes = true + // 5. Calculate the number and location of continuous dynamic nodes + let dynamicNodeCount = 1 // The current node is counted as one + let prevDynamicCount = 0 + let nextDynamicCount = 0 + + // Count consecutive dynamic nodes forward + for (let i = index - 1; i >= 0; i--) { + if (!isStaticChildNode(children[i])) { + prevDynamicCount++ + } else { + break + } + } + + // Count consecutive dynamic nodes backwards + for (let i = index + 1; i < len; i++) { + if (!isStaticChildNode(children[i])) { + nextDynamicCount++ + } else { + break + } + } + + dynamicNodeCount = 1 + prevDynamicCount + nextDynamicCount + + // For two consecutive dynamic nodes, mark both as dynamic + if (dynamicNodeCount === 2) { + return prevDynamicCount > 0 || nextDynamicCount > 0 } - if ( - !hasConsecutiveDynamicNodes && - index < len - 1 && - !isStaticElement(children[index + 1]) - ) { - hasConsecutiveDynamicNodes = true + // For three or more dynamic nodes, only mark the intermediate nodes as dynamic + else if (dynamicNodeCount >= 3) { + return prevDynamicCount > 0 && nextDynamicCount > 0 } - // Only process as dynamic if all conditions are met - return hasConsecutiveDynamicNodes + return false } diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts index 94291d4091..f0fc99ad2f 100644 --- a/packages/runtime-core/src/hydration.ts +++ b/packages/runtime-core/src/hydration.ts @@ -125,7 +125,7 @@ export function createHydrationFunctions( function nextSibling(node: Node) { let n = next(node) - // skip dynamic child anchor + // skip dynamic anchors if (n && isDynamicAnchor(n)) { n = next(n) } diff --git a/packages/runtime-vapor/__tests__/hydration.spec.ts b/packages/runtime-vapor/__tests__/hydration.spec.ts index f9021ef938..0f039674ef 100644 --- a/packages/runtime-vapor/__tests__/hydration.spec.ts +++ b/packages/runtime-vapor/__tests__/hydration.spec.ts @@ -334,13 +334,13 @@ describe('Vapor Mode hydration', () => { }, ) expect(container.innerHTML).toMatchInlineSnapshot( - `"
foo foo foo
"`, + `"
foo foo foo
"`, ) data.value = 'bar' await nextTick() expect(container.innerHTML).toMatchInlineSnapshot( - `"
bar bar bar
"`, + `"
bar bar bar
"`, ) }) @@ -439,13 +439,13 @@ describe('Vapor Mode hydration', () => { }, ) expect(container.innerHTML).toMatchInlineSnapshot( - `"
foo
-foo foo
foo
-foo
"`, + `"
foo
-foo foo
foo
-foo
"`, ) data.value = 'bar' await nextTick() expect(container.innerHTML).toMatchInlineSnapshot( - `"
bar
-bar bar
bar
-bar
"`, + `"
bar
-bar bar
bar
-bar
"`, ) })