javascript - Vue splice (Mover un elemento del array a otra ubicación en el array) no actualiza el DOM
Estoy intentando mover un elemento en un arreglo, desde la posición x a la posición 2. El código a continuación funciona y mueve el elemento a la nueva posición. Sin embargo, Vue no actualiza el DOM.
Este es el código que estoy usando:
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>
No estoy seguro de si esto se relaciona con esta nota en los documentos o no:
Cuando modificas un Array estableciendo directamente un índice (por ejemplo, arr[0]=val) o modificando su propiedad length. De manera similar, Vue.js no puede detectar estos cambios. Siempre modifica los arrays usando un método de instancia de Array, o reemplazándolo por completo. Vue proporciona un método de conveniencia arr.$set(index, value), que es azúcar sintáctica para arr.splice(index, 1, value).
Supuestamente .splice() es un método de mutación, así que no creo que deba importar. ¿Qué estoy haciendo mal aquí?
Respuesta #1
Una fuente probable de problemas es su elección de key:
<layer v-for="(layer, index) in layers" :key="index" :info="layer" :offset="index"></layer>
Inicialmente, los componentes <layer> tendrán las claves 0, 1, 2 y 3, correspondientes a las capas Layer 1 hasta Layer 4 respectivamente.
Si luego mueves la capa en la posición 0 a la posición 2, ahora las tendrás en el orden Capa 2, Capa 3, Capa 1, Capa 4. Sin embargo, las claves se determinan por índice, por lo que Capa 2 ahora tendrá un valor de clave de 0.
Cuando Vue intenta emparejar los componentes después de un re-renderizado, utiliza las claves. Así que el <layer> con una key de 0 solía corresponder a Layer 1 pero ahora corresponderá a Layer 2.
Eso no es necesariamente un problema. Capa 4 es fácil: no se ha movido, así que no se cambiará. Las otras tres se han movido, pero deberían tener sus propiedades info actualizadas en consecuencia.
Aquí es donde surge el problema de los componentes con estado. Mientras que a los tres primeros componentes se les actualizarán sus propiedades info, eso no necesariamente tendrá ningún impacto en ningún otro estado interno, como el mantenido por las propiedades data. Esas seguirán conservando el valor que tenían para el valor original de info.
La solución aquí generalmente sería usar un valor más apropiado para el key. No está claro a partir de la pregunta cuál podría ser tal valor en tu caso. En algunos casos, es posible que necesites agregar una propiedad extra dentro de cada elemento del array solo para darle una propiedad adecuada.
Lo importante es que las claves sean distintas y estén vinculadas a los elementos del arreglo. Si el name de la capa es un identificador único, entonces podrías usar eso, por ejemplo, :key="layer.name".
