Sie müssen wissen, wie AngularJS funktioniert, um es zu verstehen.
Digest-Zyklus und $ scope
AngularJS definiert in erster Linie ein Konzept eines sogenannten Digest-Zyklus . Dieser Zyklus kann als Schleife betrachtet werden, in der AngularJS prüft, ob Änderungen an allen Variablen vorgenommen wurden, die von allen $scope
s überwacht werden . Wenn Sie also $scope.myVar
in Ihrem Controller definiert haben und diese Variable zum Überwachen markiert wurde , weisen Sie AngularJS implizit an, die Änderungen myVar
in jeder Iteration der Schleife zu überwachen .
Eine natürliche Folgefrage wäre: Ist alles damit verbunden $scope
, beobachtet zu werden? Zum Glück nein. Wenn Sie auf Änderungen an jedem Objekt in Ihrem Objekt $scope
achten würden, würde die Auswertung einer Digest-Schleife schnell Ewigkeiten dauern und Sie würden schnell auf Leistungsprobleme stoßen. Aus diesem Grund hat uns das AngularJS-Team zwei Möglichkeiten gegeben, eine $scope
Variable als überwacht zu deklarieren (siehe unten).
$ watch hilft dabei, auf $ scope-Änderungen zu achten
Es gibt zwei Möglichkeiten, eine $scope
Variable als überwacht zu deklarieren .
- Indem Sie es in Ihrer Vorlage über den Ausdruck verwenden
<span>{{myVar}}</span>
- Durch manuelles Hinzufügen über den
$watch
Dienst
Anzeige 1) Dies ist das häufigste Szenario, und ich bin sicher, dass Sie es schon einmal gesehen haben, aber Sie wussten nicht, dass dadurch eine Uhr im Hintergrund erstellt wurde. Ja, das hatte es! Durch die Verwendung von AngularJS-Direktiven (z. B. ng-repeat
) können auch implizite Uhren erstellt werden.
Anzeige 2) So erstellen Sie Ihre eigenen Uhren . $watch
Mit dem Dienst können Sie Code ausführen, wenn sich ein an den angehängter Wert $scope
geändert hat. Es wird selten verwendet, ist aber manchmal hilfreich. Wenn Sie beispielsweise bei jeder Änderung von 'myVar' Code ausführen möchten, können Sie Folgendes tun:
function MyController($scope) {
$scope.myVar = 1;
$scope.$watch('myVar', function() {
alert('hey, myVar has changed!');
});
$scope.buttonClicked = function() {
$scope.myVar = 2; // This will trigger $watch expression to kick in
};
}
$ apply ermöglicht die Integration von Änderungen in den Digest-Zyklus
Sie können sich die $apply
Funktion als einen Integrationsmechanismus vorstellen . Sie sehen, jedes Mal, wenn Sie eine beobachtete Variable$scope
ändern , die direkt an das Objekt angehängt ist, weiß AngularJS, dass die Änderung stattgefunden hat. Dies liegt daran, dass AngularJS diese Änderungen bereits überwachen konnte. Wenn dies also in Code geschieht, der vom Framework verwaltet wird, wird der Digest-Zyklus fortgesetzt.
Manchmal möchten Sie jedoch einen Wert außerhalb der AngularJS-Welt ändern und sehen, dass sich die Änderungen normal ausbreiten. Beachten Sie Folgendes: Sie haben einen $scope.myVar
Wert, der im $.ajax()
Handler eines jQuery geändert wird . Dies wird irgendwann in der Zukunft geschehen. AngularJS kann es kaum erwarten, da dies nicht angewiesen wurde, auf jQuery zu warten.
Um dies anzugehen, $apply
wurde eingeführt. Damit können Sie den Verdauungszyklus explizit starten. Sie sollten dies jedoch nur verwenden, um einige Daten nach AngularJS zu migrieren (Integration mit anderen Frameworks). Verwenden Sie diese Methode jedoch niemals in Kombination mit regulärem AngularJS-Code, da AngularJS dann einen Fehler auslöst.
Wie hängt das alles mit dem DOM zusammen?
Nun, Sie sollten dem Tutorial wirklich noch einmal folgen, jetzt wo Sie das alles wissen. Der Digest-Zyklus stellt sicher, dass die Benutzeroberfläche und der JavaScript-Code synchron bleiben, indem jeder an alle $scope
s angehängte Watcher ausgewertet wird, solange sich nichts ändert. Wenn in der Digest-Schleife keine Änderungen mehr vorgenommen werden, gilt dies als abgeschlossen.
Sie können Objekte $scope
entweder explizit im Controller an das Objekt anhängen oder sie {{expression}}
direkt in der Ansicht in Form deklarieren .
Ich hoffe, das hilft, einige Grundkenntnisse über all dies zu klären.
Weitere Lesungen:
In AngularJS aktualisieren wir unsere Modelle und unsere Ansichten / Vorlagen aktualisieren das DOM "automatisch" (über integrierte oder benutzerdefinierte Anweisungen).
$ apply und $ watch, beide Scope-Methoden, sind nicht mit dem DOM verbunden.
Die Seite " Konzepte " (Abschnitt "Laufzeit") enthält eine ziemlich gute Erklärung der $ Digest-Schleife, $ Apply, der $ evalAsync-Warteschlange und der $ Watch-Liste. Hier ist das Bild, das dem Text beiliegt:
Unabhängig davon, welcher Code Zugriff auf einen Bereich hat - normalerweise Controller und Direktiven (ihre Verknüpfungsfunktionen und / oder ihre Controller) - kann ein " watchExpression " eingerichtet werden, den AngularJS anhand dieses Bereichs auswertet. Diese Auswertung erfolgt immer dann, wenn AngularJS in seine $ digest-Schleife eintritt (insbesondere in die "$ watch list" -Schleife). Sie können einzelne Bereichseigenschaften überwachen, eine Funktion definieren, um zwei Eigenschaften zusammen zu überwachen, Sie können die Länge eines Arrays überwachen usw.
Wenn Dinge "in AngularJS" passieren - z. B. geben Sie in ein Textfeld ein, in dem die AngularJS-Zweiwege-Datenbindung aktiviert ist (dh das ng-Modell verwendet), ein $ http-Rückruf ausgelöst wird usw. - $ apply wurde bereits aufgerufen, also haben wir aufgerufen befinden sich innerhalb des Rechtecks "AngularJS" in der obigen Abbildung. Alle watchExpressions werden ausgewertet (möglicherweise mehrmals - bis keine weiteren Änderungen mehr erkannt werden).
Wenn Dinge "außerhalb von AngularJS" passieren - z. B. Sie haben bind () in einer Direktive verwendet und dieses Ereignis dann ausgelöst wird, was dazu führt, dass Ihr Rückruf aufgerufen wird oder ein von jQuery registrierter Rückruf ausgelöst wird - befinden wir uns immer noch im Rechteck "Native". Wenn der Rückrufcode irgendetwas ändert, das eine $ watch beobachtet, rufen Sie $ apply auf, um in das AngularJS-Rechteck zu gelangen, wodurch die $ Digest-Schleife ausgeführt wird. AngularJS bemerkt die Änderung und macht ihre Magie.
quelle
scope.$apply(scope.model)
. Ich verstehe nicht, welche Daten übertragen werden und wie sie an die richtige Stelle im Modell übertragen werden.scope.$apply(scope.model)
wird einfachscope.model
als Winkelausdruck ausgewertet und gibt dann eine $ Digest-Schleife ein. In dem Artikel, auf den Sie verweisen,scope.$apply()
wäre dies wahrscheinlich ausreichend, da das Modell bereits überwacht wird. Die stop () - Funktion aktualisiert das Modell (ich glaube, toUpdate ist ein Verweis auf scope.model), und dann wird $ apply aufgerufen.$watch
auf der Seite, und der zweite Link ist defekt - jedenfalls ab sofort). Schmerzhafterweise haben die Archivversionen keinen asynchronen Prozess zwischengespeichert, der den Inhalt erstellt hat.AngularJS erweitert diese Ereignisschleife und erstellt so etwas wie
AngularJS context
.$ watch ()
Jedes Mal, wenn Sie etwas in der Benutzeroberfläche binden, fügen Sie ein
$watch
in eine$watch
Liste ein .Hier haben wir
$scope.user
, was an die erste Eingabe gebunden ist, und wir haben$scope.pass
, was an die zweite Eingabe gebunden ist. Dazu fügen wir$watch
der$watch
Liste zwei es hinzu .Wenn unsere Vorlage geladen wird, AKA in der Verknüpfungsphase, sucht der Compiler nach jeder Direktive und erstellt alle
$watch
erforderlichen es.AngularJS bietet
$watch
,$watchcollection
und$watch(true)
. Unten finden Sie ein übersichtliches Diagramm, in dem alle drei von Beobachtern aufgenommenen Elemente ausführlich erläutert werden .http://jsfiddle.net/2Lyn0Lkb/
$digest
SchleifeWenn der Browser ein Ereignis empfängt, das vom AngularJS-Kontext verwaltet werden kann, wird die
$digest
Schleife ausgelöst. Diese Schleife besteht aus zwei kleineren Schleifen. Einer verarbeitet die$evalAsync
Warteschlange und der andere die$watch list
. Der$digest
Wille durchläuft die Liste$watch
, die wir habenHier haben wir nur eine,
$watch
weil ng-click keine Uhren erstellt.Wir drücken den Knopf.
$digest
Schleife wird ausgeführt und fragt jede $ watch nach Änderungen.$watch
was nach Änderungen in $ scope.name gesucht hat, eine Änderung meldet, wird eine weitere$digest
Schleife erzwungen .$digest
Schleife ausführt. Das bedeutet, dass jedes Mal, wenn wir einen Buchstaben in eine Eingabe schreiben, die Schleife alle$watch
auf dieser Seite überprüft .$ apply ()
Wenn Sie aufrufen,
$apply
wenn ein Ereignis ausgelöst wird, durchläuft es den Winkelkontext. Wenn Sie es jedoch nicht aufrufen, wird es außerhalb des Ereignisses ausgeführt. So einfach ist das.$apply
ruft die$digest()
Schleife intern auf und durchläuft alle Uhren, um sicherzustellen, dass das DOM mit dem neu aktualisierten Wert aktualisiert wird.Die
$apply()
Methode löst Beobachter in der gesamten$scope
Kette aus, während die$digest()
Methode nur Beobachter in der aktuellen$scope
und ihrer Kette auslöstchildren
. Wenn keines der übergeordneten$scope
Objekte über die lokalen Änderungen Bescheid wissen muss, können Sie verwenden$digest()
.quelle
Ich fand sehr eingehenden Videos , die Abdeckung
$watch
,$apply
,$digest
und verdauen Zyklen in:AngularJS - Watcher verstehen, $ watch, $ watchGroup, $ watchCollection, ng-change
AngularJS - Verdauungszyklus verstehen (Verdauungsphase oder Verdauungsprozess oder Verdauungsschleife)
AngularJS Tutorial - Verstehen von $ apply und $ Digest (ausführlich)
Im Folgenden finden Sie einige Folien, die in diesen Videos verwendet werden, um die Konzepte zu erläutern (nur für den Fall, dass die oben genannten Links entfernt werden / nicht funktionieren).
Im obigen Bild wird "$ scope.c" nicht überwacht, da es in keiner der Datenbindungen (im Markup) verwendet wird. Die anderen beiden (
$scope.a
und$scope.b
) werden beobachtet.Aus dem obigen Bild: Basierend auf dem jeweiligen Browserereignis erfasst AngularJS das Ereignis, führt einen Digest-Zyklus durch (durchläuft alle Uhren auf Änderungen), führt Überwachungsfunktionen aus und aktualisiert das DOM. Wenn keine Browserereignisse vorliegen, kann der Digest-Zyklus manuell mit
$apply
oder ausgelöst werden$digest
.Mehr über
$apply
und$digest
:quelle
Es gibt
$watchGroup
und$watchCollection
auch. Dies$watchGroup
ist insbesondere dann sehr hilfreich, wenn Sie eine Funktion zum Aktualisieren eines Objekts mit mehreren Eigenschaften in einer Ansicht aufrufen möchten, die kein Dom-Objekt ist, z. B. eine andere Ansicht in Canvas, WebGL oder Serveranforderung.Hier der Link zur Dokumentation .
quelle
$watchCollection
aber ich sehe, dass du es bereits getan hast. Hier finden Sie eine Dokumentation von der AngularJS-Site. Sie bieten ein sehr schönes Bild der$watch
Tiefe. Beachten Sie, dass sich die Informationen am unteren Rand der Seite befinden.Lesen Sie einfach ALLE oben genannten, langweilig und schläfrig (sorry, aber es ist wahr). Sehr technisch, ausführlich, detailliert und trocken. Warum schreibe ich? Da AngularJS massiv ist, können viele miteinander verbundene Konzepte jeden verrückt machen. Ich habe mich oft gefragt, ob ich nicht klug genug bin, sie zu verstehen. Nein! Das liegt daran, dass so wenige die Technologie in einer For-Dummy-Sprache ohne alle Terminologien erklären können ! Okay, lass mich versuchen:
1) Sie sind alle ereignisgesteuerte Dinge. (Ich höre das Lachen, lese aber weiter)
Wenn Sie nicht wissen, was ereignisgesteuert ist, denken Sie, Sie platzieren eine Schaltfläche auf der Seite, schließen sie mit einer Funktion mit "On-Click" an und warten darauf, dass Benutzer darauf klicken, um die Aktionen auszulösen, die Sie in der Seite ausführen Funktion. Oder denken Sie an "Trigger" von SQL Server / Oracle.
2) $ watch ist "on-click".
Das Besondere daran ist, dass 2 Funktionen als Parameter verwendet werden: Die erste gibt den Wert des Ereignisses an, die zweite berücksichtigt den Wert ...
3) $ Digest ist der Boss, der unermüdlich nachschaut, bla-bla-bla, aber ein guter Boss.
4) $ apply gibt Ihnen die Möglichkeit, wenn Sie es manuell ausführen möchten , wie z. B. ausfallsicher (falls ein Klick nicht aktiviert wird, erzwingen Sie die Ausführung.)
In einem Restaurant,
- Kellner
sollen Bestellungen von Kunden entgegennehmen, das ist
- MANAGER läuft herum, um sicherzustellen, dass alle Kellner wach sind und auf Anzeichen von Änderungen durch Kunden reagieren. Das ist
$digest()
- EIGENTÜMER hat die ultimative Macht, jeden auf Anfrage zu fahren
$apply()
quelle