wake-up-neo.net

AngularJS: Unterschied zwischen den $ observ- und $ watch-Methoden

Ich weiß, dass sowohl Watchers als auch Observers berechnet werden, sobald sich etwas in $scope in AngularJS ändert. Aber ich konnte nicht verstehen, was genau der Unterschied zwischen den beiden ist.

Mein anfängliches Verständnis ist, dass Observers für Winkelausdrücke berechnet wird, die Bedingungen auf der HTML-Seite sind, unter denen Watchers ausgeführt wird, wenn die Funktion $scope.$watch() ausgeführt wird. Denke ich richtig?

372
Abilash

$ observ () ist eine Methode für das Attributes -Objekt und kann dies auch Dient nur zum Beobachten/Beobachten der Wertänderung eines DOM-Attributs. Es wird nur in Direktiven verwendet/aufgerufen. Verwenden Sie $ observ, wenn Sie ein DOM-Attribut beobachten müssen, das Interpolation enthält (d. H. {{}}).
ZB attr1="Name: {{name}}", dann in einer Direktive: attrs.$observe('attr1', ...).
(Wenn Sie scope.$watch(attrs.attr1, ...) versuchen, funktioniert dies aufgrund der {{}} s nicht - 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 eine Zeichenkette sein kann. Wenn der Ausdruck ein String ist, wird $ parse 'd (d. H. Ausgewertet als Angular expression ) in eine Funktion. (Diese Funktion wird bei jedem Digest-Zyklus aufgerufen.) Der String-Ausdruck darf keine {{}} enthalten. $ watch ist eine Methode für das Scope -Objekt. Sie kann also überall dort verwendet/aufgerufen werden, wo Sie Zugriff auf ein Scope-Objekt haben, also in

  • ein Controller - ein beliebiger Controller - ein Controller, der über ng-view, ng-controller oder einen Anweisungscontroller erstellt wurde
  • eine Verknüpfungsfunktion in einer Direktive, da diese auch Zugriff auf einen Gültigkeitsbereich hat

Da Zeichenfolgen als Angular Ausdrücke ausgewertet werden, wird $ watch häufig verwendet, wenn Sie eine Modell-/Bereichseigenschaft beobachten/beobachten möchten. Zum Beispiel attr1="myModel.some_prop", dann in einer Controller- oder Link-Funktion: 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, der wahrscheinlich nicht Ihren Wünschen entspricht.)

Wie in den Kommentaren zur Antwort von @ PrimosK erläutert, werden alle $ observes und $ watches alle Digest-Zyklus überprüft.

Richtlinien mit isolierten Bereichen sind komplizierter. Wenn die '@'-Syntax verwendet wird, können Sie ein DOM-Attribut oder $ watch beobachten, das Interpolation enthält (d. H. {{}}). (Der Grund, warum es mit $ watch funktioniert, ist, dass die '@'-Syntax die Interpolation für uns ausführt, daher sieht $ watch einen String ohne {{}}.) Um es einfacher zu machen, sich zu merken, welcher Um wann zu verwenden, empfehle ich, $ observ auch für diesen Fall zu verwenden.

Um all dies zu testen, habe ich ein Plunker geschrieben, das zwei Direktiven definiert. Einer (d1) erstellt keinen neuen Bereich, der andere (d2) erstellt einen isolierten Bereich. Jede Direktive hat die gleichen sechs Attribute. Jedes Attribut wird sowohl beobachtet als auch überwacht.

<div d1 attr1="{{prop1}}-test" attr2="prop2" attr3="33" attr4="'a_string'"
        attr5="a_string" attr6="{{1+aNumber}}"></div>

Sehen Sie sich das Konsolenprotokoll an, um die Unterschiede zwischen $ observ und $ watch in der Verknüpfungsfunktion zu sehen. Klicken Sie dann auf den Link und sehen Sie, welche $ observes und $ watches durch die vom Click-Handler vorgenommenen Eigenschaftsänderungen ausgelöst werden.

Beachten Sie, dass beim Ausführen der Link-Funktion noch keine Attribute ausgewertet werden, die {{}} enthalten (wenn Sie also versuchen, die Attribute zu untersuchen, erhalten Sie undefined). Die einzige Möglichkeit, die interpolierten Werte anzuzeigen, besteht in der Verwendung von $ observ (oder $ watch, wenn ein Isolationsbereich mit '@' verwendet wird). Daher ist das Abrufen der Werte dieser Attribute eine asynchrone Operation. (Und deshalb brauchen wir die Funktionen $ observ und $ watch.)

Manchmal braucht man $ beobachten oder $ beobachten nicht. Wenn Ihr Attribut beispielsweise eine Zahl oder einen Booleschen Wert (keine Zeichenfolge) enthält, werten Sie es einfach einmal aus: attr1="22", und geben Sie dann beispielsweise in Ihrer Verknüpfungsfunktion Folgendes ein: var count = scope.$eval(attrs.attr1). Wenn es sich nur um eine konstante Zeichenfolge handelt - attr1="my string" -, verwenden Sie in Ihrer Direktive einfach attrs.attr1 ($ eval () ist nicht erforderlich).

Siehe auch Vojtas Google-Gruppenpost about $ watch expressions.

606
Mark Rajcok

Wenn ich Ihre Frage richtig verstehe, fragen Sie, was ist der Unterschied, wenn Sie den Listener-Callback mit $watch oder mit $observe registrieren.

Callback registerd mit $watch wird ausgelöst, wenn $digest ausgeführt wird.

Mit $observe registrierter Callback wird aufgerufen, wenn sich der Wert von Attributen ändert, die Interpolation enthalten (z. B. attr="{{notJetInterpolated}}"). 


In der Direktive können Sie beide auf sehr ähnliche Weise verwenden:

    attrs.$observe('attrYouWatch', function() {
         // body
    });

oder

    scope.$watch(attrs['attrYouWatch'], function() {
         // body
    });
23
PrimosK

Ich denke das ist ziemlich offensichtlich:

  • $ observ wird zur Verknüpfung von Direktiven verwendet.
  • $ watch wird für scope verwendet, um Änderungen seiner Werte zu überwachen.

Beachte : Beide Funktionen haben zwei Argumente,

$observe/$watch(value : string, callback : function);
  • value : ist immer ein Stringverweis auf das überwachte Element (der Name einer Bereichsvariablen oder der Name des zu überwachenden Attributs der Direktive)
  • Callback : die auszuführende Funktion der Form function (oldValue, newValue)

Ich habe ein gemacht plunker , so dass Sie tatsächlich einen Überblick über deren Nutzung bekommen. Ich habe die Chamäleon-Analogie verwendet, um die Bilddarstellung zu vereinfachen.

1
vdegenne

Warum unterscheidet sich $ observ von $ watch?

Die watchExpression wird ausgewertet und mit dem vorherigen Wert jedes Digest () - Zyklus verglichen. Wenn sich der watchExpression-Wert ändert, wird die Watch-Funktion aufgerufen.

$ observ ist spezifisch für die Suche nach interpolierten Werten. Wenn der Attributwert einer Direktive interpoliert wird, z. B. dir-attr="{{ scopeVar }}", wird die Beobachtungsfunktion nur aufgerufen, wenn der interpolierte Wert gesetzt ist (und daher, wenn $ digest bereits festgestellt hat, dass Aktualisierungen vorgenommen werden müssen). Grundsätzlich gibt es bereits einen Beobachter für die Interpolation, und die $ observ-Funktion huckt davon.

Siehe $ observ & $ set in compile.js

0
Niko