]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix: treat v-if/v-else/v-else-if as a single node
authordaiwei <daiwei521@126.com>
Mon, 4 Aug 2025 14:12:06 +0000 (22:12 +0800)
committerdaiwei <daiwei521@126.com>
Tue, 5 Aug 2025 06:22:51 +0000 (14:22 +0800)
packages/compiler-vapor/src/generators/operation.ts
packages/compiler-vapor/src/generators/template.ts
packages/compiler-vapor/src/ir/index.ts
packages/compiler-vapor/src/transforms/transformChildren.ts
packages/compiler-vapor/src/transforms/vIf.ts

index 83fcc9a2835e40fd924cba2da7a8ca14627935fc..2069c9f6a6673f1ee5a3aab32a22159d7065d675 100644 (file)
@@ -169,7 +169,7 @@ function genInsertionState(
   context: CodegenContext,
 ): CodeFragment[] {
   const { seenChildIndexes } = context
-  let { parent, childIndex, anchor } = operation
+  const { parent, childIndex, anchor } = operation
   const insertionAnchor =
     anchor == null
       ? undefined
@@ -178,11 +178,14 @@ function genInsertionState(
         : `n${anchor}`
 
   // the index of next block node, used to locate node during hydration
+  // only passed when anchor is null and childIndex > 0
   let index: number | undefined
-  if (anchor == null) {
+  if (anchor == null && childIndex) {
     const existingOffset = seenChildIndexes.get(parent!)
-    index = existingOffset ? existingOffset + 1 : childIndex
-    if (index) seenChildIndexes.set(parent!, index)
+    seenChildIndexes.set(
+      parent!,
+      (index = existingOffset ? existingOffset + 1 : childIndex),
+    )
   }
 
   return [
index 30710143328ac3267e578f114829a091290fc7c5..d7d29d5d155ad2166e0d030611262502260e3f65 100644 (file)
@@ -53,9 +53,11 @@ export function genChildren(
   const { children } = dynamic
 
   let offset = 0
+  let ifBranchCount = 0
   let prev: [variable: string, elementIndex: number] | undefined
 
   for (const [index, child] of children.entries()) {
+    if (child.isIfBranch) ifBranchCount++
     if (child.flags & DynamicFlag.NON_TEMPLATE) {
       offset--
     }
@@ -97,7 +99,11 @@ export function genChildren(
             // this ensures that insertionAnchor points to the current node itself
             // rather than its next sibling, since insertionAnchor is used as the
             // hydration node
-            `${asAnchor ? index - 1 : index}`
+            `${
+              (asAnchor ? index - 1 : index) -
+              // treat v-if/v-else/v-else-if as a single node
+              ifBranchCount
+            }`
 
       if (elementIndex === 0) {
         pushBlock(...genCall(helper('child'), from, childIndex))
index 90d063b8b04c3a5f66545b1c6aa54051975692ec..96110207d5a03fe26d7b641dfcc0e814ff6f4233 100644 (file)
@@ -272,6 +272,7 @@ export interface IRDynamicInfo {
   hasDynamicChild?: boolean
   operation?: OperationNode
   needsKey?: boolean
+  isIfBranch?: boolean
 }
 
 export interface IREffect {
index 5480187ebd911441fbc7e0c6ad17cafff91075fa..71e31718909dd46bb18ce0a5a23ffb0d671c166a 100644 (file)
@@ -92,7 +92,7 @@ function processDynamicChildren(context: TransformContext<ElementNode>) {
             prevDynamics,
             context,
             -1 /* prepend */,
-            children.findIndex(c => c === prevDynamics[0]),
+            getChildIndex(children, prevDynamics[0]),
           )
         }
         prevDynamics = []
@@ -106,7 +106,7 @@ function processDynamicChildren(context: TransformContext<ElementNode>) {
       prevDynamics,
       context,
       undefined,
-      children.findIndex(c => c === prevDynamics[0]),
+      getChildIndex(children, prevDynamics[0]),
     )
   }
 }
@@ -134,3 +134,17 @@ function registerInsertion(
     }
   }
 }
+
+function getChildIndex(
+  children: IRDynamicInfo[],
+  child: IRDynamicInfo,
+): number {
+  let index = 0
+  for (const c of children) {
+    // treat v-if/v-else/v-else-if as a single node
+    if (c.isIfBranch) continue
+    if (c === child) break
+    index++
+  }
+  return index
+}
index 2426fa0215eeee6a0360b22f67c9562494016d5e..cc135863ece4dfc33c0300237d1fc20952a2ad2a 100644 (file)
@@ -57,6 +57,7 @@ export function processIf(
       }
     }
   } else {
+    context.dynamic.isIfBranch = true
     // check the adjacent v-if
     const siblingIf = getSiblingIf(context, true)