Ich möchte auf Änderungen in einem Wörterbuch achten, aber aus irgendeinem Grund wird Watch Callback nicht aufgerufen.
Hier ist ein Controller, den ich benutze:
function MyController($scope) {
$scope.form = {
name: 'my name',
surname: 'surname'
}
$scope.$watch('form', function(newVal, oldVal){
console.log('changed');
});
}
Hier ist Geige .
Ich gehe davon aus, dass $ watch-Rückruf bei jeder Änderung des Namens oder Nachnamens ausgelöst wird. Dies geschieht jedoch nicht.
Was ist der richtige Weg, dies zu tun?
Rufen Sie $watch
mit true
als drittem Argument auf:
$scope.$watch('form', function(newVal, oldVal){
console.log('changed');
}, true);
Beim Vergleich zweier komplexer Objekte in JavaScript werden diese standardmäßig auf "Verweis" - Gleichheit geprüft. Dabei werden Sie gefragt, ob sich die beiden Objekte auf dasselbe beziehen, und nicht auf "Wert". Dabei werden die Werte aller Eigenschaften dieser Objekte geprüft Objekte sind gleich.
Gemäß der Angular-Dokumentation ist der dritte Parameter für objectEquality
:
Bei
objectEquality == true
wird die Ungleichung von watchExpression gemäß der Funktionangular.equals
bestimmt. Um den Wert des Objekts zum späteren Vergleich zu speichern, wird die Funktionangular.copy
verwendet. Das bedeutet daher, dass das Beobachten komplexer Objekte nachteilige Auswirkungen auf das Gedächtnis und die Leistung hat.
Das form
-Objekt ändert sich nicht, nur die name
-Eigenschaft ist
aktualisiert Geige
function MyController($scope) {
$scope.form = {
name: 'my name',
}
$scope.changeCount = 0;
$scope.$watch('form.name', function(newVal, oldVal){
console.log('changed');
$scope.changeCount++;
});
}
Kleiner Leistungstipp wenn jemand einen Datastore-Dienst mit Schlüssel -> Wertepaaren hat:
Wenn Sie einen Dienst namens dataStore haben, können Sie einen Zeitstempel aktualisieren, wenn sich Ihr Big Data-Objekt ändert. Auf diese Weise beobachten Sie nicht das gesamte Objekt, sondern beobachten nur einen Zeitstempel für die Änderung.
app.factory('dataStore', function () {
var store = { data: [], change: [] };
// when storing the data, updating the timestamp
store.setData = function(key, data){
store.data[key] = data;
store.setChange(key);
}
// get the change to watch
store.getChange = function(key){
return store.change[key];
}
// set the change
store.setChange = function(key){
store.change[key] = new Date().getTime();
}
});
Und in einer Direktive beobachten Sie nur den Zeitstempel, der geändert werden soll
app.directive("myDir", function ($scope, dataStore) {
$scope.dataStore = dataStore;
$scope.$watch('dataStore.getChange("myKey")', function(newVal, oldVal){
if(newVal !== oldVal && newVal){
// Data changed
}
});
});
Der Grund dafür, dass Ihr Code nicht funktioniert, liegt darin, dass $watch
standardmäßig auf die Überprüfung überprüft. Kurz gesagt, stellen Sie sicher, dass das Objekt, das an es übergeben wird, ein neues Objekt ist. In Ihrem Fall ändern Sie jedoch nur eine Eigenschaft eines Formularobjekts, ohne ein neues zu erstellen. Damit dies funktioniert, können Sie als dritten Parameter true
übergeben.
$scope.$watch('form', function(newVal, oldVal){
console.log('invoked');
}, true);
Es wird funktionieren, aber Sie können $ watchCollection verwenden, was effizienter ist als $ watch, da $watchCollection
auf flache Eigenschaften des Formularobjekts achtet. Z.B.
$scope.$watchCollection('form', function (newVal, oldVal) {
console.log(newVal, oldVal);
});
Wenn Sie nach Änderungen an Formularobjekten suchen, verwenden Sie am besten den Beobachtungsansatz$watchCollection
. Bitte beachten Sie die offiziellen Dokumentationen für verschiedene Leistungsmerkmale.
Versuche dies:
function MyController($scope) {
$scope.form = {
name: 'my name',
surname: 'surname'
}
function track(newValue, oldValue, scope) {
console.log('changed');
};
$scope.$watch('form.name', track);
}
Für jeden, der auf eine Änderung an einem Objekt innerhalb eines Arrays von Objekten achten möchte, schien dies für mich zu funktionieren (wie bei den anderen Lösungen auf dieser Seite nicht):
function MyController($scope) {
$scope.array = [
data1: {
name: 'name',
surname: 'surname'
},
data2: {
name: 'name',
surname: 'surname'
},
]
$scope.$watch(function() {
return $scope.data,
function(newVal, oldVal){
console.log(newVal, oldVal);
}, true);