]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-vapor): resolve multiple vFor rendering issues (#13714)
authoredison <daiwei521@126.com>
Wed, 30 Jul 2025 01:25:35 +0000 (09:25 +0800)
committerGitHub <noreply@github.com>
Wed, 30 Jul 2025 01:25:35 +0000 (09:25 +0800)
packages/runtime-vapor/__tests__/for.spec.ts
packages/runtime-vapor/src/apiCreateFor.ts

index 4e4dcf0e98f2d17604e8ebf7e7d52994553e260b..572c8af85ae6a4a3e5bb2d48bd9905b635cf46ed 100644 (file)
@@ -778,7 +778,7 @@ describe('createFor', () => {
       )
     })
 
-    test.todo('prepend', async () => {
+    test('prepend', async () => {
       const arr = ref<number[]>([4, 5])
       const { host, html } = render(arr)
       expect(host.children.length).toBe(2)
@@ -940,7 +940,7 @@ describe('createFor', () => {
       )
     })
 
-    test.todo('remove from beginning and insert at end', async () => {
+    test('remove from beginning and insert at end', async () => {
       const arr = ref<number[]>([1, 2, 3])
       const { host, html } = render(arr)
       expect(host.children.length).toBe(3)
@@ -1028,7 +1028,7 @@ describe('createFor', () => {
       )
     })
 
-    test.todo('move to left & replace', async () => {
+    test('move to left & replace', async () => {
       const arr = ref<number[]>([1, 2, 3, 4, 5])
       const { host, html } = render(arr)
       expect(host.children.length).toBe(5)
@@ -1044,7 +1044,7 @@ describe('createFor', () => {
       )
     })
 
-    test.todo('move to left and leaves hold', async () => {
+    test('move to left and leaves hold', async () => {
       const arr = ref<number[]>([1, 4, 5])
       const { host, html } = render(arr)
       expect(host.children.length).toBe(3)
@@ -1058,24 +1058,21 @@ describe('createFor', () => {
       expect(html()).toBe(`<span>4</span><span>6</span><!--for-->`)
     })
 
-    test.todo(
-      'moved and set to undefined element ending at the end',
-      async () => {
-        const arr = ref<number[]>([2, 4, 5])
-        const { host, html } = render(arr)
-        expect(host.children.length).toBe(3)
-        expect(html()).toBe(
-          `<span>2</span><span>4</span><span>5</span><!--for-->`,
-        )
+    test('moved and set to undefined element ending at the end', async () => {
+      const arr = ref<number[]>([2, 4, 5])
+      const { host, html } = render(arr)
+      expect(host.children.length).toBe(3)
+      expect(html()).toBe(
+        `<span>2</span><span>4</span><span>5</span><!--for-->`,
+      )
 
-        arr.value = [4, 5, 3]
-        await nextTick()
-        expect(host.children.length).toBe(3)
-        expect(html()).toBe(
-          `<span>4</span><span>5</span><span>3</span><!--for-->`,
-        )
-      },
-    )
+      arr.value = [4, 5, 3]
+      await nextTick()
+      expect(host.children.length).toBe(3)
+      expect(html()).toBe(
+        `<span>4</span><span>5</span><span>3</span><!--for-->`,
+      )
+    })
 
     test('reverse element', async () => {
       const arr = ref<number[]>([1, 2, 3, 4, 5, 6, 7, 8])
@@ -1323,7 +1320,7 @@ describe('createFor', () => {
       }).render()
     }
 
-    test.todo('move a key in non-keyed nodes with a size up', async () => {
+    test('move a key in non-keyed nodes with a size up', async () => {
       const arr = ref<any[]>([1, 'a', 'b', 'c'])
       const { host, html } = define({
         setup() {
index dbc9ebc83195f996fc8d2e0eb81f3d050a9d6189..864bebb8a8d0f7ec15ff28d6eaaca8798842b091 100644 (file)
@@ -196,12 +196,15 @@ export const createFor = (
             endOffset++
             continue
           }
-          if (endOffset !== 0) {
-            anchorFallback = normalizeAnchor(newBlocks[currentIndex + 1].nodes)
-          }
           break
         }
 
+        if (endOffset !== 0) {
+          anchorFallback = normalizeAnchor(
+            newBlocks[newLength - endOffset].nodes,
+          )
+        }
+
         while (startOffset < sharedBlockCount - endOffset) {
           const currentItem = getItem(source, startOffset)
           const currentKey = getKey(...currentItem)
@@ -251,12 +254,7 @@ export const createFor = (
           previousKeyIndexPairs.length = previousKeyIndexInsertIndex
 
           const previousKeyIndexMap = new Map(previousKeyIndexPairs)
-          const blocksToMount: [
-            blockIndex: number,
-            blockItem: ReturnType<typeof getItem>,
-            blockKey: any,
-            anchorOffset: number,
-          ][] = []
+          const operations: (() => void)[] = []
 
           const relocateOrMountBlock = (
             blockIndex: number,
@@ -269,21 +267,30 @@ export const createFor = (
               const reusedBlock = (newBlocks[blockIndex] =
                 oldBlocks[previousIndex])
               update(reusedBlock, ...blockItem)
-              insert(
-                reusedBlock,
-                parent!,
-                anchorOffset === -1
-                  ? anchorFallback
-                  : normalizeAnchor(newBlocks[anchorOffset].nodes),
-              )
               previousKeyIndexMap.delete(blockKey)
+              if (previousIndex !== blockIndex) {
+                operations.push(() =>
+                  insert(
+                    reusedBlock,
+                    parent!,
+                    anchorOffset === -1
+                      ? anchorFallback
+                      : normalizeAnchor(newBlocks[anchorOffset].nodes),
+                  ),
+                )
+              }
             } else {
-              blocksToMount.push([
-                blockIndex,
-                blockItem,
-                blockKey,
-                anchorOffset,
-              ])
+              operations.push(() =>
+                mount(
+                  source,
+                  blockIndex,
+                  anchorOffset === -1
+                    ? anchorFallback
+                    : normalizeAnchor(newBlocks[anchorOffset].nodes),
+                  blockItem,
+                  blockKey,
+                ),
+              )
             }
           }
 
@@ -303,7 +310,7 @@ export const createFor = (
             relocateOrMountBlock(i, blockItem, blockKey, -1)
           }
 
-          const useFastRemove = blocksToMount.length === newLength
+          const useFastRemove = operations.length === newLength
 
           for (const leftoverIndex of previousKeyIndexMap.values()) {
             unmount(
@@ -322,21 +329,9 @@ export const createFor = (
             }
           }
 
-          for (const [
-            blockIndex,
-            blockItem,
-            blockKey,
-            anchorOffset,
-          ] of blocksToMount) {
-            mount(
-              source,
-              blockIndex,
-              anchorOffset === -1
-                ? anchorFallback
-                : normalizeAnchor(newBlocks[anchorOffset].nodes),
-              blockItem,
-              blockKey,
-            )
+          // perform mount and move operations
+          for (const action of operations) {
+            action()
           }
         }
       }