2013-12-23 8 views
24

Meine Absicht ist, ein Modell innerhalb des Umfangs zu beobachten und den Unterschied zwischen altem Wert und neuem Wert zu finden.

Allerdings fand ich alten Wert und neuen Wert sind alle gleich aus dem folgenden Code.

app.controller('MyCtrl', function($scope, $timeout){ 
    $scope.markers = {}; 
    $scope.$watchCollection('markers', function(newValue, oldValue){ 
    console.log('being watched oldValue:', oldValue, 'newValue:', newValue); 
    }); 
    $timeout(function() { 
    $scope.markers.foo = 1; 
    }, 500); 
    $timeout(function() { 
    $scope.markers.bar = 2; 
    }, 500); 
}); 

Ausgang:

being watched oldValue: Object {} newValue: Object {} script.js:6 
being watched oldValue: Object {foo: 1} newValue: Object {foo: 1} script.js:6 
being watched oldValue: Object {foo: 1, bar: 2} newValue: Object {foo: 1, bar: 2} 

Warum sind sie gleich, und wenn es gewollt, dann warum?

hier ist der Code, http://plnkr.co/edit/rfMCF4x6CmVVT957DPSS?p=preview

+0

Entweder die Dokumentation ist nicht up-to-date oder es ein Fehler ist. 'newValue === oldValue' gibt' false' an, also würde ich eher denken, dass es ein Fehler ist. –

+4

Stellt sich heraus, es ist ein bekannter Fehler: https://github.com/angular/angular.js/issues/2621 – KayakDave

+0

Ich nahm an, dass $ watchCollection Abkürzung von Deep $ watch ist. Es scheint nicht. – allenhwkim

Antwort

35

können Sie $watch stattdessen verwenden, das zu funktionieren scheint. Wenn Sie auch alle Eigenschaften des Objekts beobachten möchten (wie Sie es gerade tun), müssen Sie der Uhr true als dritten Parameter hinzufügen. Dies sorgt für eine tiefe Überwachung.

Here is a working plunker.

JS:

app = angular.module('myApp',[]); 

app.controller('MyCtrl', function($scope, $timeout){ 
    $scope.markers = {}; 
    $scope.$watch('markers', function(newValue, oldValue){ 
    console.log('being watched oldValue:', oldValue, 'newValue:', newValue); 
    }, true); 
    $timeout(function() { 
    $scope.markers.foo = 1; 
    }, 500); 
    $timeout(function() { 
    $scope.markers.bar = 2; 
    }, 500); 
}); 
+0

Die Dokumentation für watchCollection sagt: "Shallow überwacht die Eigenschaften eines Objekts und feuert, wenn sich eine der Eigenschaften ändert (bei Arrays bedeutet dies, die Array-Elemente zu beobachten; bei Objekt-Maps bedeutet dies, dass die Eigenschaften beobachtet werden)." Die Verwendung von watchCollection für ein Objekt ist also korrekt. –

+0

@JBNizet Seltsam, dann habe ich zuerst versucht, einen tiefen Blick (true) für die watchCollection zu machen, aber es hat nicht funktioniert. Regelmäßige Tiefenwache tat es jedoch. :) Ich habe die Antwort bearbeitet, also mache ich keine Vermutungen zwischen den beiden. –

+1

JB, watchCollection ist defekt. Ja, es wird ausgelöst, wenn sich die Eigenschaften ändern, nein, es werden nicht die alten Werte gespeichert, um sie zurückzugeben, wie in der Dokumentation angegeben. Stattdessen erhalten Sie eine Kopie der neuen Daten in einem neuen und separaten Objekt. https://github.com/angular/angular.js/issues/2621 – Noishe

1

Die Werte übergeben werden als Parameter

$scope.$watch('foo', function (newValue, oldValue) { 
    // ... 
} 
12

Ich fand, dass es sehr nützlich ist, wenn der neue und alte Wert gleich zu überprüfen (in Werten) sind und den Prozess überspringen, wenn das der Fall ist unerwartetes Verhalten zu vermeiden. Sie können angular.equals verwenden, um das zu erreichen. Hier ein Beispiel:

JS:

$scope.$watch('myObject', function(newValue, oldValue){ 
    if(angular.equals(newValue, oldValue)){ 
     return; // simply skip that 
    } 
}); 
Verwandte Themen