Просмотр исходного кода

fix(runtime-vapor): update v-for object aliases when reusing blocks

daiwei 2 недель назад
Родитель
Сommit
172a954c02
2 измененных файлов с 52 добавлено и 2 удалено
  1. 49 0
      packages/runtime-vapor/__tests__/for.spec.ts
  2. 3 2
      packages/runtime-vapor/src/apiCreateFor.ts

+ 49 - 0
packages/runtime-vapor/__tests__/for.spec.ts

@@ -311,6 +311,55 @@ describe('createFor', () => {
     expect(host.innerHTML).toBe('<!--for-->')
     expect(host.innerHTML).toBe('<!--for-->')
   })
   })
 
 
+  test('unkeyed object source updates key and index aliases', async () => {
+    const data = ref<Record<string, number>>({ a: 1 })
+
+    const { host } = define(() => {
+      return createFor(
+        () => data.value,
+        (item, key, index) => {
+          const span = document.createElement('li')
+          renderEffect(() => {
+            span.innerHTML = `${key.value}${index.value}. ${item.value}`
+          })
+          return span
+        },
+      )
+    }).render()
+
+    expect(host.innerHTML).toBe('<li>a0. 1</li><!--for-->')
+
+    data.value = { b: 2 }
+    await nextTick()
+
+    expect(host.innerHTML).toBe('<li>b0. 2</li><!--for-->')
+  })
+
+  test('keyed object source updates key and index aliases when reusing a block', async () => {
+    const data = ref<Record<string, number>>({ a: 1, c: 3 })
+
+    const { host } = define(() => {
+      return createFor(
+        () => data.value,
+        (item, key, index) => {
+          const span = document.createElement('li')
+          renderEffect(() => {
+            span.innerHTML = `${key.value}${index.value}. ${item.value}`
+          })
+          return span
+        },
+        item => item,
+      )
+    }).render()
+
+    expect(host.innerHTML).toBe('<li>a0. 1</li><li>c1. 3</li><!--for-->')
+
+    data.value = { b: 1, d: 4 }
+    await nextTick()
+
+    expect(host.innerHTML).toBe('<li>b0. 1</li><li>d1. 4</li><!--for-->')
+  })
+
   test('de-structured value', async () => {
   test('de-structured value', async () => {
     const list = ref([{ name: '1' }, { name: '2' }, { name: '3' }])
     const list = ref([{ name: '1' }, { name: '2' }, { name: '3' }])
     function reverse() {
     function reverse() {

+ 3 - 2
packages/runtime-vapor/src/apiCreateFor.ts

@@ -202,7 +202,8 @@ export const createFor = (
         // unkeyed fast path
         // unkeyed fast path
         const commonLength = Math.min(newLength, oldLength)
         const commonLength = Math.min(newLength, oldLength)
         for (let i = 0; i < commonLength; i++) {
         for (let i = 0; i < commonLength; i++) {
-          update((newBlocks[i] = oldBlocks[i]), getItem(source, i)[0])
+          const item = getItem(source, i)
+          update((newBlocks[i] = oldBlocks[i]), ...item)
         }
         }
         for (let i = oldLength; i < newLength; i++) {
         for (let i = oldLength; i < newLength; i++) {
           mount(source, i)
           mount(source, i)
@@ -261,7 +262,7 @@ export const createFor = (
           const oldBlock = oldBlocks[i]
           const oldBlock = oldBlocks[i]
           const oldKey = oldBlock.key
           const oldKey = oldBlock.key
           if (oldKey === currentKey) {
           if (oldKey === currentKey) {
-            update((newBlocks[i] = oldBlock), currentItem[0])
+            update((newBlocks[i] = oldBlock), ...currentItem)
           } else {
           } else {
             queuedBlocks[queuedBlocksLength++] = [i, currentItem, currentKey]
             queuedBlocks[queuedBlocksLength++] = [i, currentItem, currentKey]
             oldKeyIndexPairs[oldKeyIndexPairsLength++] = [oldKey, i]
             oldKeyIndexPairs[oldKeyIndexPairsLength++] = [oldKey, i]