Ich habe ein Array namens people
, das Objekte wie folgt enthält:
Vor
[
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 32},
{id: 2, name: 'Joe', age: 38}
]
Es kann sich ändern:
Nach dem
[
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 33},
{id: 2, name: 'Joe', age: 38}
]
Beachten Sie, dass Frank gerade 33 geworden ist.
Ich habe eine App, in der ich versuche, das Personenarray zu beobachten. Wenn sich einer der Werte ändert, protokolliere ich die Änderung:
<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>
Ich habe dies auf die Frage gestützt , die ich gestern zu Array-Vergleichen gestellt und die am schnellsten funktionierende Antwort ausgewählt habe.
An diesem Punkt erwarte ich also ein Ergebnis von: { id: 1, name: 'Frank', age: 33 }
Aber alles, was ich zurück in die Konsole bekomme, ist (wenn man bedenkt, dass ich es in einer Komponente hatte):
[Vue warn]: Error in watcher "people"
(found in anonymous component - use the "name" option for better debugging messages.)
Und in dem Codepen, den ich erstellt habe , ist das Ergebnis ein leeres Array und nicht das geänderte Objekt, das sich geändert hat, was ich erwartet hätte.
Wenn jemand vorschlagen könnte, warum dies geschieht oder wo ich hier falsch gelaufen bin, wäre er sehr dankbar, vielen Dank!
quelle
Ich habe die Implementierung geändert, um Ihr Problem zu lösen. Ich habe ein Objekt erstellt, um die alten Änderungen zu verfolgen und damit zu vergleichen. Sie können es verwenden, um Ihr Problem zu lösen.
Hier habe ich eine Methode erstellt, bei der der alte Wert in einer separaten Variablen gespeichert und dann in einer Uhr verwendet wird.
Siehe den aktualisierten Codepen
quelle
vm.$data
, danke!Es ist gut definiertes Verhalten. Sie können den alten Wert für ein mutiertes Objekt nicht abrufen . Das liegt daran, dass sich sowohl das
newVal
als aucholdVal
auf dasselbe Objekt beziehen. Vue wird nicht eine alte Kopie eines Objekts halten , dass Sie mutiert.Hatten Sie ersetzt das Objekt mit einem anderen, würde Vue Sie haben mit der richtigen Referenzen zur Verfügung gestellt.
Lesen Sie den
Note
Abschnitt in den Dokumenten. (vm.$watch
)Mehr dazu hier und hier .
quelle
Dies ist, was ich benutze, um ein Objekt tief zu beobachten. Meine Anforderung bestand darin, die untergeordneten Felder des Objekts zu beobachten.
quelle
Die Komponentenlösung und die Deep-Clone-Lösung haben ihre Vorteile, aber auch Probleme:
Manchmal möchten Sie Änderungen an abstrakten Daten verfolgen - es ist nicht immer sinnvoll, Komponenten um diese Daten herum zu erstellen.
Das Deep-Cloning Ihrer gesamten Datenstruktur bei jeder Änderung kann sehr teuer sein.
Ich denke, es gibt einen besseren Weg. Wenn Sie alle Elemente in einer Liste anzeigen möchten und wissen möchten, welches Element in der Liste geändert wurde, können Sie benutzerdefinierte Beobachter für jedes Element separat einrichten, z. B.:
Mit dieser Struktur
handleChange()
erhalten Sie das spezifische Listenelement, das sich geändert hat - von dort aus können Sie jede gewünschte Behandlung ausführen.Ich habe hier auch ein komplexeres Szenario dokumentiert , falls Sie Elemente zu Ihrer Liste hinzufügen / entfernen (anstatt nur die bereits vorhandenen Elemente zu bearbeiten).
quelle