Tengo una matriz llamada people
que contiene objetos de la siguiente manera:
antes de
[
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 32},
{id: 2, name: 'Joe', age: 38}
]
Puede cambiar:
Después
[
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 33},
{id: 2, name: 'Joe', age: 38}
]
Note que Frank acaba de cumplir 33 años.
Tengo una aplicación en la que estoy tratando de ver la matriz de personas y cuando alguno de los valores cambia, entonces registro el cambio:
<style>
input {
display: block;
}
</style>
<div id="app">
<input type="text" v-for="(person, index) in people" v-model="people[index].age" />
</div>
<script>
new Vue({
el: '#app',
data: {
people: [
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 32},
{id: 2, name: 'Joe', age: 38}
]
},
watch: {
people: {
handler: function (val, oldVal) {
// Return the object that changed
var changed = val.filter( function( p, idx ) {
return Object.keys(p).some( function( prop ) {
return p[prop] !== oldVal[idx][prop];
})
})
// Log it
console.log(changed)
},
deep: true
}
}
})
</script>
Basé esto en la pregunta que hice ayer sobre las comparaciones de matrices y seleccioné la respuesta de trabajo más rápida.
Entonces, en este punto espero ver un resultado de: { id: 1, name: 'Frank', age: 33 }
Pero todo lo que obtengo en la consola es (teniendo en cuenta que lo tenía en un componente):
[Vue warn]: Error in watcher "people"
(found in anonymous component - use the "name" option for better debugging messages.)
Y en el codepen que hice , el resultado es una matriz vacía y no el objeto modificado que cambió, que sería lo que esperaba.
Si alguien pudiera sugerir por qué está sucediendo esto o dónde me he equivocado aquí, sería muy apreciado, ¡muchas gracias!
fuente
He cambiado la implementación para resolver su problema, hice un objeto para rastrear los cambios anteriores y compararlo con eso. Puede usarlo para resolver su problema.
Aquí creé un método, en el que el valor anterior se almacenará en una variable separada y, luego, se usará en un reloj.
Ver el codepen actualizado
fuente
vm.$data
, ¡gracias!Es un comportamiento bien definido. No puede obtener el valor anterior para un objeto mutado . Eso es porque tanto el
newVal
y seoldVal
refieren al mismo objeto. Vue no conservará una copia antigua de un objeto que mutó.Si hubiera reemplazado el objeto por otro, Vue le habría proporcionado las referencias correctas.
Lea la
Note
sección en los documentos. (vm.$watch
)Más sobre esto aquí y aquí .
fuente
Esto es lo que uso para observar en profundidad un objeto. Mi requisito era observar los campos secundarios del objeto.
fuente
La solución de componentes y la solución de clonación profunda tienen sus ventajas, pero también presentan problemas:
A veces, desea realizar un seguimiento de los cambios en los datos abstractos; no siempre tiene sentido crear componentes en torno a esos datos.
La clonación profunda de toda su estructura de datos cada vez que realiza un cambio puede resultar muy costosa.
Creo que hay una forma mejor. Si desea ver todos los elementos de una lista y saber qué elemento de la lista cambió, puede configurar observadores personalizados en cada elemento por separado, así:
Con esta estructura,
handleChange()
recibirá el elemento de la lista específico que cambió; desde allí, puede realizar el manejo que desee.También he documentado un escenario más complejo aquí , en caso de que esté agregando / eliminando elementos a su lista (en lugar de solo manipular los elementos que ya están allí).
fuente