v-for ref behaves differently under production and development
Vue version
3.2.29
Link to minimal reproduction
Steps to reproduce
- Click anywhere on the preview 2 times
- Change to production and click again 2 times anywhere on the preview
What is expected?
On each click one element is removed from the list. The itemRefs variable should also be updated with the corresponding number of elements
What is actually happening?
Under production everything works as expected, under development the ref array is "lagging" behind. After one click, the list has 2 elements and the ref array still 3. After a second click, the list has 1 element and the ref array has now 2.
System Info
No response
Any additional comments?
Every 2 seconds the itemRefs variable is printed on the console. There you can see that it is actually updated correctly after each click (in both dev and prod scenarios)
I don't know... the order is not really the problem here. The source and the ref array are somehow different. The change does also not appear inside a watcher.
Like with the clicks, the watcher works fine in production, but in development, it's like if the updated is not sent to the UI and the watcher
Edit: the comment I responded to was deleted
modify your demo, look like more directly :
I also think is a bug, the Model can not match View
I also think this is a bug. When the list changes and the update is triggered, toDisplayString will be called. At this time, the dom has not changed, so the itemRefs value is still 3 divs, and then the converted string is the same as before the update. When comparing dynamicchildren , no updates were made. Also I found that this problem also exists in production mode if the setup syntactic sugar is not used. play
With the composition API it does not work either in production or development. See here
As a temporary fix, you can create a watcher on the list, then await nextTick()
, temporary set the references to []
and finally store the references back into the array. Like this
watch(list.value, async () => {
await nextTick();
const temp = itemRefs.value;
itemRefs.value = [];
itemRefs.value = temp;
})