core icon indicating copy to clipboard operation
core copied to clipboard

Vue 2 migration build WATCH_ARRAY triggers on deep value modification

Open thecodewarrior opened this issue 5 months ago • 5 comments

Vue version

3.4.38 (compat)

Link to minimal reproduction

https://stackblitz.com/edit/vitejs-vite-cpcesj?file=src%2FApp.vue

Steps to reproduce

  1. Create a new project with the Vue 2 migration build
  2. Create an array with object elements (e.g. [{foo: 0}, {foo: 1}]) and add a watch on it
  3. Replace the array (arr = [...arr])
  4. Mutate the array (arr.push({foo: 2}))
  5. Modify the contents of one of the elements (arr[0].foo++)

What is expected?

The watch should be triggered when the array is replaced or mutated, but should not be triggered when the contents of the array elements are modified (Vue 2 repro)

What is actually happening?

The watch is triggered in all three cases, on replacement, mutation, and deep modification

System Info

No response

Any additional comments?

The compat is implemented here in createWatcher, and it's implemented by doing a deep traversal of array values. The Vue 2 behavior can be reproduced by instead calling array.slice(0, 0) there, which creates a reactive dependency on TrackOpTypes.ITERATE. The internal shallowReadArray function may also be more appropriate to call in internal code.

thecodewarrior avatar Sep 09 '24 20:09 thecodewarrior