J'ai un tableau appelé people
qui contient des objets comme suit:
Avant
[
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 32},
{id: 2, name: 'Joe', age: 38}
]
Cela peut changer:
Après
[
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 33},
{id: 2, name: 'Joe', age: 38}
]
Remarquez que Frank vient d'avoir 33 ans.
J'ai une application dans laquelle j'essaie de regarder le tableau des personnes et lorsque l'une des valeurs change, enregistrez le changement:
<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>
Je me suis basé sur la question que j'ai posée hier sur les comparaisons de tableaux et j'ai sélectionné la réponse la plus rapide.
Donc, à ce stade, je m'attends à voir un résultat de: { id: 1, name: 'Frank', age: 33 }
Mais tout ce que je reçois dans la console est (en gardant à l'esprit que je l'avais dans un composant):
[Vue warn]: Error in watcher "people"
(found in anonymous component - use the "name" option for better debugging messages.)
Et dans le codepen que j'ai créé , le résultat est un tableau vide et non l'objet modifié qui a changé, ce à quoi je m'attendais.
Si quelqu'un pouvait suggérer pourquoi cela se produit ou où je me suis trompé ici, ce serait grandement apprécié, merci beaucoup!
la source
J'ai changé l'implémentation de celui-ci pour résoudre votre problème, j'ai créé un objet pour suivre les anciennes modifications et le comparer avec cela. Vous pouvez l'utiliser pour résoudre votre problème.
Ici, j'ai créé une méthode dans laquelle l'ancienne valeur sera stockée dans une variable séparée et, qui sera ensuite utilisée dans une montre.
Voir le codepen mis à jour
la source
vm.$data
, merci!C'est un comportement bien défini. Vous ne pouvez pas obtenir l'ancienne valeur d'un objet muté . En effet , à la fois la
newVal
et seoldVal
réfèrent au même objet. Vue ne conservera pas une ancienne copie d'un objet que vous avez muté.Si vous aviez remplacé l'objet par un autre, Vue vous aurait fourni les références correctes.
Lisez la
Note
section dans la documentation. (vm.$watch
)Plus d'informations ici et ici .
la source
C'est ce que j'utilise pour observer en profondeur un objet. Mon exigence était de regarder les champs enfants de l'objet.
la source
La solution de composant et la solution de clone profond ont leurs avantages, mais aussi des problèmes:
Parfois, vous souhaitez suivre les modifications des données abstraites - il n'est pas toujours logique de créer des composants autour de ces données.
Le clonage en profondeur de l'ensemble de votre structure de données à chaque fois que vous apportez une modification peut être très coûteux.
Je pense qu'il y a une meilleure façon. Si vous souhaitez regarder tous les éléments d'une liste et savoir quel élément de la liste a changé, vous pouvez configurer des observateurs personnalisés sur chaque élément séparément, comme ceci:
Avec cette structure,
handleChange()
recevra l'élément de liste spécifique qui a changé - à partir de là, vous pouvez faire n'importe quelle manipulation que vous voulez.J'ai également documenté un scénario plus complexe ici , au cas où vous ajouteriez / supprimeriez des éléments à votre liste (plutôt que de manipuler uniquement les éléments déjà présents).
la source