Subscribe on changes!

Unintended data exposed

avatar
Aug 31st 2023

Vue version

2.6.11

Link to minimal reproduction

https://codesandbox.io/s/sweet-fast-xk4dl3?file=/package.json:262-268

Steps to reproduce

Press the add button

What is expected?

Both the upper and lower regions must be exposed with the same prop and local data

What is actually happening?

The area below is normal, but the area above shows different values of prop and local data

System Info

No response

Any additional comments?

No response

avatar
Aug 31st 2023

I think this StackOverflow answer has explained the issue well: https://stackoverflow.com/a/75175749/2302258 Generally, using the array index as the key is a bad idea.

avatar
Aug 31st 2023

@sodatea

Thank you for your reply. But I don't think the link explains everything.

because When the key is set to :key="${index}-${member}" 1-tomato 2-tomato 3-tomato key is set

After all, isn't this:key="index" and :key="${index}-${member}" the same thing?

avatar
Aug 31st 2023

It's about the patching algorithm: https://v2.vuejs.org/v2/api/#v-for

The default behavior of v-for will try to patch the elements in-place without moving them. To force it to reorder elements, you need to provide an ordering hint with the key special attribute:

Let's walk through the demo step by step:

  • Originally, the first list item is Prop: apple | Local Data: apple, the index is 0 and the name is apple.
  • In the :key="index" case:
    • The original key was 0
    • After unshifting orange to the array, the first list item becomes orange, yet the index is still 0;
    • The new key is 0
    • So Vue sees the two keys are identical; the item should be patched rather than removed-then-recreated;
    • So mounted isn't called. localName stays as apple;
    • Vue rerenders the component with the new prop value and applies it to the real DOM. The list item becomes Prop: orange | Local Data: apple
  • in the :key="${index}-${member}" case
    • The original key was 0-apple
    • After unshifting orange to the array, the first list item becomes orange, yet the index is still 0;
    • The new key is 0-orange
    • Vue sees two different keys; the item must have changed. The existing one should be removed
    • A new list item is created. The mounted lifecycle hook is called, localName is in sync with the latest prop value.
avatar
Aug 31st 2023

It might be easier to understand if you:

  • add an <input> in the <li>
  • type something in each input
  • then click the add button
  • see which inputs' states are preserved, and which are not
avatar
Sep 1st 2023

@sodatea

Thank you for your answer

But I have another question

As shown in the video attached below, if you keep putting the same input value, isn't the situation where the keys overlap the same? (0-orange)

https://github.com/vuejs/core/assets/47649108/9b49bd15-df21-4c2d-82e8-9a2de71485f0