From bf5bf1b527bdb2713ea6c8a4c829423eb1dba615 Mon Sep 17 00:00:00 2001 From: Doctorwu Date: Wed, 6 Mar 2024 11:25:39 +0800 Subject: [PATCH 1/2] fix(reactiviy): fix arrays don't reactive when mutate index close #10455 --- .../reactivity/__tests__/reactiveArray.spec.ts | 18 ++++++++++++++++++ packages/reactivity/src/reactiveEffect.ts | 3 +++ 2 files changed, 21 insertions(+) diff --git a/packages/reactivity/__tests__/reactiveArray.spec.ts b/packages/reactivity/__tests__/reactiveArray.spec.ts index 1c6fcefd592..88c5e67e486 100644 --- a/packages/reactivity/__tests__/reactiveArray.spec.ts +++ b/packages/reactivity/__tests__/reactiveArray.spec.ts @@ -1,6 +1,7 @@ import { isReactive, reactive, toRaw } from '../src/reactive' import { isRef, ref } from '../src/ref' import { effect } from '../src/effect' +import { watchSyncEffect } from 'vue' describe('reactivity/reactive/Array', () => { test('should make Array reactive', () => { @@ -99,6 +100,23 @@ describe('reactivity/reactive/Array', () => { expect(fn).toHaveBeenCalledTimes(1) }) + test("should reactive when mutate array's index", () => { + const original = [1, 2, 3] + const observed = reactive(original) + const fn = vitest.fn(() => { + observed[0] + }) + watchSyncEffect(fn) + + delete observed[0] + expect(0 in observed).toBe(false) + expect(fn).toHaveBeenCalledTimes(2) + + observed[0] = 2 + expect(0 in observed).toBe(true) + expect(fn).toHaveBeenCalledTimes(3) + }) + test('shift on Array should trigger dependency once', () => { const arr = reactive([1, 2, 3]) const fn = vi.fn() diff --git a/packages/reactivity/src/reactiveEffect.ts b/packages/reactivity/src/reactiveEffect.ts index 6bf0e75115a..0647bb233ad 100644 --- a/packages/reactivity/src/reactiveEffect.ts +++ b/packages/reactivity/src/reactiveEffect.ts @@ -32,6 +32,9 @@ export const MAP_KEY_ITERATE_KEY = Symbol(__DEV__ ? 'Map key iterate' : '') */ export function track(target: object, type: TrackOpTypes, key: unknown) { if (shouldTrack && activeEffect) { + if (isArray(target) && typeof key === 'number' && isIntegerKey(`${key}`)) { + key = `${key}` + } let depsMap = targetMap.get(target) if (!depsMap) { targetMap.set(target, (depsMap = new Map())) From d021d1246bbd000af574363969dd19894fd7e691 Mon Sep 17 00:00:00 2001 From: Doctorwu Date: Wed, 6 Mar 2024 14:41:08 +0800 Subject: [PATCH 2/2] feat: remove integer judgement --- packages/reactivity/src/reactiveEffect.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/reactivity/src/reactiveEffect.ts b/packages/reactivity/src/reactiveEffect.ts index 0647bb233ad..eb9d805922b 100644 --- a/packages/reactivity/src/reactiveEffect.ts +++ b/packages/reactivity/src/reactiveEffect.ts @@ -32,7 +32,7 @@ export const MAP_KEY_ITERATE_KEY = Symbol(__DEV__ ? 'Map key iterate' : '') */ export function track(target: object, type: TrackOpTypes, key: unknown) { if (shouldTrack && activeEffect) { - if (isArray(target) && typeof key === 'number' && isIntegerKey(`${key}`)) { + if (isArray(target) && typeof key === 'number') { key = `${key}` } let depsMap = targetMap.get(target)