$observe() ist eine Methode des Attributes-Objekts und kann daher nur verwendet werden, um den Wert einer DOM-Attributänderung zu beobachten. Es wird nur innerhalb von Direktiven verwendet/aufgerufen. Verwenden Sie $observe, wenn Sie ein DOM-Attribut beobachten möchten, das Interpolation enthält (d.h. {{}}'s).
Zum Beispiel attr1="Name: {{name}}"
, dann in einer Direktive: attrs.$observe('attr1', ...)
.
(Wenn Sie scope.$watch(attrs.attr1, ...)
versuchen, wird es aufgrund der {{}}s nicht funktionieren - Sie erhalten undefined
. Verwenden Sie $watch für alles andere.
$watch() ist komplizierter. Es kann einen "Ausdruck" beobachten, wobei der Ausdruck entweder eine Funktion oder ein String sein kann. Wenn der Ausdruck ein String ist, wird er $parse'd (d.h. als Angular-Ausdruck ausgewertet) in eine Funktion. (Es ist diese Funktion, die in jedem Digest-Zyklus aufgerufen wird.) Der String-Ausdruck darf keine {{}}s enthalten. $watch ist eine Methode des Scope-Objekts, so dass es verwendet/aufgerufen werden kann, wo immer Sie Zugriff auf ein Scope-Objekt haben, also in
- einem Controller - jedem Controller - einem, der über ng-view, ng-controller oder einen Direktivencontroller erstellt wurde
- einer Verknüpfungsfunktion in einer Direktive, da diese ebenfalls Zugriff auf einen Scope hat
Weil Strings als Angular-Ausdrücke ausgewertet werden, wird $watch oft verwendet, wenn Sie ein Modell/Scope-Eigenschaft beobachten möchten. Zum Beispiel attr1="myModel.some_prop"
, dann in einem Controller oder Verknüpfungsfunktion: scope.$watch('myModel.some_prop', ...)
oder scope.$watch(attrs.attr1, ...)
(oder scope.$watch(attrs['attr1'], ...)
).
(Wenn Sie attrs.$observe('attr1')
versuchen, erhalten Sie den String myModel.some_prop
, was wahrscheinlich nicht das ist, was Sie wollen.)
Wie in den Kommentaren zu @PrimosK's Antwort erläutert wurde, werden alle $observes und $watches bei jedem Digest-Zyklus überprüft.
Direktiven mit isolierten Scopes sind komplizierter. Wenn die '@'-Syntax verwendet wird, können Sie ein DOM-Attribut, das Interpolation enthält (d.h. {{}}s), $observe oder $watch. (Der Grund, warum es mit $watch funktioniert, liegt darin, dass die '@'-Syntax für uns die Interpolation durchführt, daher sieht $watch einen String ohne {{}}s.) Um es einfacher zu machen, sich zu merken, wann welches verwendet werden soll, schlage ich vor, $observe auch in diesem Fall zu verwenden.
Um all dies zu testen, habe ich einen Plunker geschrieben, der zwei Direktiven definiert. Eine (d1
) erstellt keinen neuen Scope, die andere (d2
) erstellt einen isolierten Scope. Jede Direktive hat dieselben sechs Attribute. Jedes Attribut wird sowohl $observe't als auch $watch't.
Schauen Sie sich die Konsolenausgabe an, um die Unterschiede zwischen $observe und $watch in der Verknüpfungsfunktion zu sehen. Klicken Sie dann auf den Link und sehen Sie, welche $observes und $watches durch die Änderungen der Eigenschaft ausgelöst werden, die durch den Klick-Handler vorgenommen wurden.
Beachten Sie, dass, wenn die Verknüpfungsfunktion ausgeführt wird, alle Attribute, die {{}}s enthalten, noch nicht ausgewertet werden (wenn Sie also versuchen, die Attribute zu überprüfen, erhalten Sie undefined
). Der einzige Weg, um die interpolierten Werte zu sehen, ist die Verwendung von $observe (oder $watch bei Verwendung eines isolierten Scopes mit '@'). Das Abrufen der Werte dieser Attribute ist also ein asynchroner Vorgang. (Und das ist der Grund, warum wir die $observe- und $watch-Funktionen benötigen.)
Manchmal benötigen Sie kein $observe oder $watch. Zum Beispiel, wenn Ihr Attribut eine Zahl oder einen booleschen Wert enthält (keinen String), bewerten Sie es einfach einmal: attr1="22"
, dann in Ihrer Verknüpfungsfunktion zum Beispiel: var count = scope.$eval(attrs.attr1)
. Wenn es nur einen konstanten String enthält - attr1="mein String"
- verwenden Sie einfach attrs.attr1
in Ihrer Direktive (kein Bedarf für $eval()).
Sehen Sie auch Vojtas Google-Group-Post über $watch-Ausdrücke.