Skip to content

Commit 6779bff

Browse files
authored
feat(runtime-core): support dynamic / external array in v-memo (#4255)
1 parent 2641422 commit 6779bff

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

packages/runtime-core/__tests__/helpers/withMemo.spec.ts

+41
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,47 @@ describe('v-memo', () => {
1010
return [el, vm]
1111
}
1212

13+
test('on with external array', async () => {
14+
const [el, vm] = mount({
15+
template: `<div v-memo="arr">{{ arr[0] }} {{ arr[1] }} {{arr[2] ?? '_' }} ({{c}})</div>{{c}}`,
16+
data: () => ({ arr: [0, 0], c: 0 })
17+
})
18+
expect(el.innerHTML).toBe(`<div>0 0 _ (0)</div>0`)
19+
20+
let [x, y, z] = [0, 1, 2]
21+
22+
// change at index x - should update
23+
vm.arr[x]++
24+
vm.c++
25+
await nextTick()
26+
expect(el.innerHTML).toBe(`<div>1 0 _ (1)</div>1`)
27+
28+
// change at index y - should update
29+
vm.arr[y]++
30+
vm.c++
31+
await nextTick()
32+
expect(el.innerHTML).toBe(`<div>1 1 _ (2)</div>2`)
33+
34+
// noop change - should NOT update
35+
vm.arr[x] = vm.arr[0]
36+
vm.arr[y] = vm.arr[1]
37+
vm.c++
38+
await nextTick()
39+
expect(el.innerHTML).toBe(`<div>1 1 _ (2)</div>3`)
40+
41+
// add item 3rd item - should update
42+
vm.arr[z] = 0
43+
vm.c++
44+
await nextTick()
45+
expect(el.innerHTML).toBe(`<div>1 1 0 (4)</div>4`)
46+
47+
// remove 3rd item - should update
48+
vm.arr = vm.arr.slice(0, vm.arr.length - 1)
49+
vm.c++
50+
await nextTick()
51+
expect(el.innerHTML).toBe(`<div>1 1 _ (5)</div>5`)
52+
})
53+
1354
test('on normal element', async () => {
1455
const [el, vm] = mount({
1556
template: `<div v-memo="[x]">{{ x }} {{ y }}</div>`,

packages/runtime-core/src/helpers/withMemo.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,17 @@ export function withMemo(
1111
return cached
1212
}
1313
const ret = render()
14-
ret.memo = memo
14+
15+
// shallow clone
16+
ret.memo = memo.slice()
1517
return (cache[index] = ret)
1618
}
1719

1820
export function isMemoSame(cached: VNode, memo: any[]) {
1921
const prev: any[] = cached.memo!
22+
if (prev.length != memo.length) {
23+
return false
24+
}
2025
for (let i = 0; i < prev.length; i++) {
2126
if (prev[i] !== memo[i]) {
2227
return false

0 commit comments

Comments
 (0)