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..eb9d805922b 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') { + key = `${key}` + } let depsMap = targetMap.get(target) if (!depsMap) { targetMap.set(target, (depsMap = new Map()))