]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(runtime-core): support dynamic / external array in v-memo (#4255)
authorlidlanca <8693091+lidlanca@users.noreply.github.com>
Mon, 9 Aug 2021 19:39:22 +0000 (15:39 -0400)
committerGitHub <noreply@github.com>
Mon, 9 Aug 2021 19:39:22 +0000 (15:39 -0400)
packages/runtime-core/__tests__/helpers/withMemo.spec.ts
packages/runtime-core/src/helpers/withMemo.ts

index 93aac0d8f4b00a9346d472920187102b86129f68..5d6590bd9096a1fa7a03af79d5788697cf5f1198 100644 (file)
@@ -10,6 +10,47 @@ describe('v-memo', () => {
     return [el, vm]
   }
 
+  test('on with external array', async () => {
+    const [el, vm] = mount({
+      template: `<div v-memo="arr">{{ arr[0] }} {{ arr[1] }} {{arr[2] ?? '_' }} ({{c}})</div>{{c}}`,
+      data: () => ({ arr: [0, 0], c: 0 })
+    })
+    expect(el.innerHTML).toBe(`<div>0 0 _ (0)</div>0`)
+
+    let [x, y, z] = [0, 1, 2]
+
+    // change at index x - should update
+    vm.arr[x]++
+    vm.c++
+    await nextTick()
+    expect(el.innerHTML).toBe(`<div>1 0 _ (1)</div>1`)
+
+    // change at index y - should update
+    vm.arr[y]++
+    vm.c++
+    await nextTick()
+    expect(el.innerHTML).toBe(`<div>1 1 _ (2)</div>2`)
+
+    // noop change - should NOT update
+    vm.arr[x] = vm.arr[0]
+    vm.arr[y] = vm.arr[1]
+    vm.c++
+    await nextTick()
+    expect(el.innerHTML).toBe(`<div>1 1 _ (2)</div>3`)
+
+    // add item  3rd item - should update
+    vm.arr[z] = 0
+    vm.c++
+    await nextTick()
+    expect(el.innerHTML).toBe(`<div>1 1 0 (4)</div>4`)
+
+    // remove 3rd item - should update
+    vm.arr = vm.arr.slice(0, vm.arr.length - 1)
+    vm.c++
+    await nextTick()
+    expect(el.innerHTML).toBe(`<div>1 1 _ (5)</div>5`)
+  })
+
   test('on normal element', async () => {
     const [el, vm] = mount({
       template: `<div v-memo="[x]">{{ x }} {{ y }}</div>`,
index 43b1fc282bc5147c29e42ae67fde213cf3add6e2..3e40365ea3f34703add68e91300f87d18dac90e1 100644 (file)
@@ -11,12 +11,17 @@ export function withMemo(
     return cached
   }
   const ret = render()
-  ret.memo = memo
+
+  // shallow clone
+  ret.memo = memo.slice()
   return (cache[index] = ret)
 }
 
 export function isMemoSame(cached: VNode, memo: any[]) {
   const prev: any[] = cached.memo!
+  if (prev.length != memo.length) {
+    return false
+  }
   for (let i = 0; i < prev.length; i++) {
     if (prev[i] !== memo[i]) {
       return false