简体   繁体   中英

Vue splice (Move array item to another location in array) not updating the DOM

I am trying to move one item in an array, at position x to position 2 . The below code works and moves the item to the new position. However, vue doesn't update the DOM .

This is the code that I am using:

export default class LayersPanel extends Vue {
  @ProvideReactive() public layers: any[] = [
    { name: 'Layer 1' }, { name: 'Layer 2' }, { name: 'Layer 3' }, { name: 'Layer 4' }
  ]
  public onDragDrop(evt: DragEvent) {
    let offset = parseInt(evt.dataTransfer.getData('text/plain'))
    this.layers.splice(2, 0, this.layers.splice(offset, 1)[0])
  }
}
<template>
  <div class="layers-panel" @dragover="onDragOver" @drop="onDragDrop">
    <layer v-for="(layer, index) in layers" :key="index" :info="layer" :offset="index"></layer>
  </div>
</template>

I am not sure if this relates to this note in the docs or not:

When you modify an Array by directly setting an index (eg arr[0] = val) or modifying its length property. Similarly, Vue.js cannot pickup these changes. Always modify arrays by using an Array instance method, or replacing it entirely. Vue provides a convenience method arr.$set(index, value) which is syntax sugar for arr.splice(index, 1, value).

Supposedly .splice() is a mutation method, so I don't think that it should matter. What am I doing wrong here?

A likely source of problems is your choice of key :

<layer v-for="(layer, index) in layers" :key="index" :info="layer" :offset="index"></layer>

Initially the <layer> components will have keys 0 , 1 , 2 and 3 , corresponding to layers Layer 1 through to Layer 4 respectively.

If you then move the layer in position 0 to position 2 then you'll now have them in the order Layer 2 , Layer 3 , Layer 1 , Layer 4 . However, the keys are determined by index so Layer 2 will now have a key value of 0 .

When Vue tries to pair up the components after a re-render it uses the keys. So the <layer> with a key of 0 used to correspond to Layer 1 but it will now correspond to Layer 2 .

That isn't necessarily a problem. Layer 4 is easy: it hasn't moved, so it won't be changed. The other three have moved but they should have their info props updated accordingly.

This is where the problem of stateful components comes in. While the first three components will have their info props updated that won't necessarily have any impact on any other internal state, such as that held by data properties. Those will still retain the value they had for the original info value.

The solution here would generally be to use a more appropriate value for the key . It is unclear from the question what such a value might be in your case. In some cases you may need to add an extra property within each array item just to give it a suitable property.

The important thing is that the keys are distinct and tied to the array items. If the layer's name is a unique identifier then you could use that, eg :key="layer.name" .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM