$ anwenden () und $ digest () sind zwei Kernkonzepte in AngularJs, aber manchmal sind sie verwirrend. Um zu verstehen, wie AngularJs funktioniert, müssen Sie zunächst verstehen, wie $ anwenden () und $ digest () arbeiten. Dieser Artikel soll erklären, was $ anwenden () und $ digest () sind und wie sie in der täglichen Codierung angewendet werden.
1. Explore $ Apply () und $ digest ()
1.1. Zwei-Wege-Datenbindung verstehen und $ watch ();
AngularJS bietet eine sehr coole Funktion namens Zwei-Wege-Datenbindung, die die Art und Weise, wie wir unseren Code schreiben, erheblich vereinfacht. Datenbindung bedeutet, dass bei Daten in der Ansicht Änderungen automatisch an die Umfangsdaten zurückgeführt werden, was bedeutet, dass das Zielfernrohrmodell automatisch aktualisiert wird. In ähnlicher Weise werden die Daten in der Ansicht auf den neuesten Wert aktualisiert, wenn sich das Umfangsmodell ändert. Wie macht AngularJs das? Wenn Sie einen Ausdruck wie {{Amodel}} schreiben, setzt AngularJS einen Beobachter für Sie auf dem Umfangsmodell, mit dem die Ansicht aktualisiert wird, wenn sich die Daten ändert. Der Beobachter hier ist der gleiche wie der Beobachter, den Sie in AngularJS einstellen werden:
$ scope.
Der zweite Parameter, der an $ watch () übergeben wurde, ist eine Rückruffunktion, die aufgerufen wird, wenn sich der Wert von Amodel ändert. Wenn sich Amodel ändert, ist es nicht schwer zu verstehen, dass diese Rückruffunktion aufgerufen wird, um die Ansicht zu aktualisieren, aber es gibt immer noch ein sehr wichtiges Problem! Woher wissen AngularJs, wann man diese Rückruffunktion nennt? Mit anderen Worten, wie hat AngularJs die entsprechende Rückruffunktion aufgerufen, wenn es weiß, dass sich Amodel geändert hat? Wird es regelmäßig eine Funktion ausführen, um zu überprüfen, ob sich die Daten im Umfangsmodell geändert haben? Hier kommt die $ Digest -Schleife ins Spiel.
In der $ Digest -Schleife werden Beobachter abgefeuert. Wenn ein Beobachter ausgelöst wird, erkennt AngularJs das Zielfernrohrmodell. Wenn es sich ändert, wird die mit dem Beobachter verknüpfte Rückruffunktion aufgerufen. Die nächste Frage ist also, wann die $ Digest -Schleife auf verschiedene Weise beginnt.
Nachdem $ scope $ digest () bezeichnet wurde, beginnt die $ digest -Schleife. Angenommen, Sie ändern eine Daten im Umfang der Handlerfunktion, die einer NG-Klick-Direktive entspricht. AngularJS löst automatisch eine $ digest-Schleife aus, indem Sie $ digest () aufrufen. Wenn die $ Digest -Schleife beginnt, löst sie jeden Beobachter aus. Diese Beobachter prüfen, ob sich der aktuelle Modellwert im Umfang von dem Modellwert unterscheidet, der das letzte Mal berechnet wurde. Wenn es anders ist, wird die entsprechende Rückruffunktion ausgeführt. Das Ergebnis dieser Funktion ist, dass der Inhalt des Ausdrucks in der Ansicht (Anmerkung des Übersetzers: wie {{Amodel}}) aktualisiert wird. Zusätzlich zur NG-Klick-Richtlinie gibt es einige andere integrierte Richtlinien und Dienste, mit denen Sie Modelle (z. B. NG-Model, $ Timeout usw.) ändern und automatisch eine $ Digest-Schleife auslösen können.
Bisher ist es nicht schlecht! Es gibt jedoch ein kleines Problem. Im obigen Beispiel nennt AngularJS $ digest () nicht direkt, sondern $ scope. Daher beginnt eine $ Digest -Schleife bei $ rootscope, wodurch dann auf alle Kinderbereiche zugreifen wird.
HINWEIS: $ scope. $ Bewerben () nennt $ rootscope automatisch. $ Digest ().
Die $ Apply () -Methode hat zwei Formulare:
Der erste akzeptiert eine Funktion als Parameter, führt die Funktion aus und löst eine $ Digest -Schleife aus.
Der zweite Typ akzeptiert keine Parameter und löst nur eine $ Digest -Schleife aus. Wir werden sofort sehen, warum die erste Form besser ist.
1.2. Wann soll man die Methode $ Apply () manuell anrufen?
Wenn AngularJs unseren Code immer in eine Funktion einwickeln und $ apply () übergeben, um eine $ Digest -Schleife zu starten, müssen dann die $ Apply () -Methode manuell aufrufen? Tatsächlich hat AngularJS eine sehr klare Anforderung dafür, dass es nur dafür verantwortlich ist, automatisch auf Änderungen zu reagieren, die im AngularJS -Kontext auftreten (d. H. Änderungen an Modellen, die in der $ Apply () -Methode auftreten). So macht AngularJS 'eingebaute Richtlinie sie, sodass sich alle Modelländerungen in der Ansicht widerspiegeln. Wenn Sie das Modell jedoch überall außerhalb des AngularJS -Kontextes ändern, müssen Sie AngularJs benachrichtigen, indem Sie $ apply () manuell aufrufen. Es ist wie AngularJs zu sagen, dass Sie einige Modelle geändert haben und hoffen, dass AngularJs Ihnen helfen kann, Beobachter zu lösen, um richtig zu reagieren.
Wenn Sie beispielsweise SetTimeOut () in JavaScript verwenden, um ein Zielfernrohrmodell zu aktualisieren, kann AngularJS nicht wissen, was Sie sich geändert haben. In diesem Fall liegt es in Ihrer Verantwortung, $ Apply () anzurufen und eine $ Digest -Schleife auszulösen, indem Sie ihn anrufen. Wenn Sie eine Anweisung haben, einen DOM -Ereignis -Listener festzulegen und einige Modelle in diesem Hörer zu ändern, müssen Sie auch $ Apply () manuell anrufen, um sicherzustellen, dass die Änderungen in der Ansicht korrekt reflektiert werden.
Schauen wir uns ein Beispiel an. Join Sie haben eine Seite, auf der Sie nach zwei Sekunden eine Nachricht anzeigen möchten, sobald die Seite geladen ist. Ihre Implementierung könnte so aussehen:
HTML:
<Body ng-App = "MyApp"> <div ng-controller = "messageController"> Verzögerte Nachricht: {{message}} </div> </body>JavaScript:
/ * Was passiert ohne $ apply () */ Angular.module ('myapp', []). Controller ('MessageController', Funktion ($ scope) {$ scope.getMessage = function () {setTimeout (function () {$ scope.message = 'eingedrungen nach 3 Sekunden, console.log ($'; } $ scope.getMessage ();Wenn Sie dieses Beispiel ausführen, werden Sie feststellen, dass die Konsole nach zwei Sekunden das aktualisierte Modell zeigt, die Ansicht wird jedoch nicht aktualisiert. Vielleicht kennen Sie bereits den Grund, das heißt, wir haben vergessen, die $ Apply () -Methode anzurufen. Daher müssen wir GetMessage () wie folgt ändern:
/ * Was passiert mit $ anwenden */angular.module ('MyApp', []). Controller ('MessageController', Funktion ($ scope) {$ scope.getMessage = function () {setTimeout (function () {$ scope. $ scope.message);Wenn Sie das obige Beispiel ausführen, werden Sie feststellen, dass die Ansicht auch nach zwei Sekunden aktualisiert wird. Die einzige Änderung ist, dass unser Code jetzt in $ Scope eingewickelt ist.
Hinweis: Übrigens sollten Sie $ Timeout Service anstelle von setTimeout () verwenden, da ersterer $ Apply () für Sie anruft, sodass Sie ihn nicht manuell anrufen müssen.
Beachten Sie außerdem, dass Sie im obigen Code nach dem Ändern des Modells auch manuell $ apply () ohne Parameter aufrufen können, genau wie die folgenden:
$ scope.getMessage = function () {setTimeout (function () {$ scope.message = 'nach zwei Sekunden abgeholt'; console.log ('meldung:' + $ scope.message); $ scope. };Der obige Code verwendet die zweite Form von $ apply (), dh die Form ohne Parameter. Es ist wichtig zu beachten, dass Sie immer die $ apply () -Methode verwenden sollten, die eine Funktion als Parameter nimmt. Dies liegt daran, dass die Funktion, wenn Sie eine Funktion in $ anwenden () übergeben, in einen Versuch eingewickelt wird ... Catch -Block. Sobald eine Ausnahme eingetreten ist, wird die Ausnahme vom $ ExceptionSandler -Service verarbeitet.
Die Situation der Verwendung von $ apply () lautet wie folgt:
• Sie können normalerweise $ Apply () basierend auf der von Angular bereitgestellten Richtlinie aufrufen, die in der Ansicht verwendet werden kann. Alle NG- [Event] -Richtlinien (wie NG-Klick, NG-Keypress) werden $ Apply () anrufen.
• Darüber hinaus können Sie sich auch auf eine Reihe von eckigen integrierten Diensten verlassen, um $ digest () zu rufen. Beispielsweise wird der $ http -Dienst $ Apply () aufgerufen, nachdem die XHR -Anfrage abgeschlossen und der Aktualisierungsrückgabewert ausgelöst wird.
• Wenn wir Ereignisse manuell verarbeiten, verwenden wir Frameworks von Drittanbietern (z. B. JQuery, Facebook API) oder Call setTimeout (), wir können die Funktion $ Apply () verwenden, um Angular Return eine $ Digest-Schleife zu erstellen.
Anruf setTimeout ():
<! DocType html> <html ng-App = "MyApp"> <kopf> <titels> $ Scope. $ Anwenden () Verwendung </title> <meta charset = "utf-8"> <Skript src = "http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script> </head> <body> <div1 = "div1" ng-controller = "MyText"> <div> {text}} </div> <einput = "btn" Typ "{{{text {text} </div> </div> </div> </div> </div> </div> < value = "jQuery-event"> </input> </div> </body> </html> <script type = "text/javaScript"> var MyModule = Angular.module ('myApp', []); MYMODULE.CONTROLLER ("mytext", function ($ scope) {$ scope.text = "place"; setTimeout (function () {$ scope.text = "Wert, der nach der Zeit festgelegt ist"; $ scope. </script>Verwenden Sie Frameworks von Drittanbietern (wie JQuery, Facebook-API):
<! DocType html> <html ng-app = "myapp"> <kopf> <titels> $ scope. $ Anwenden () use src = "http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script> <body> <div1 "div1" ng-controller = "mytext> <div> {{{{text}} value = "jQuery-event"> </input> </div> </body> </html> <script type = "text/javaScript"> var MyModule = Angular.module ('myApp', []); MYMODULE.CONTROLLER ("MyText", Funktion ($ scope) {$ scope.text = "place";}); $ (function () {$ ("#btn"). click (function () {var $ scope = $ ("#btn"). scope (); $ scope.text = "Wert in jQuery festgelegt"; $ scope. $ anwenden ();}) </script>1.3. Wie oft wird die $ Digest Loop ausgeführt?
Wenn eine $ digest -Schleife ausgeführt wird, werden Beobachter ausgeführt, um zu überprüfen, ob sich die Modelle in SCOPE geändert haben. Wenn eine Änderung auftritt, wird die entsprechende Listener -Funktion ausgeführt. Dies beinhaltet ein wichtiges Thema. Was ist, wenn die Hörerfunktion selbst ein Zielfernrohrmodell ändern wird? Wie werden AngularJs mit dieser Situation umgehen?
Die Antwort ist, dass die $ Digest -Schleife nicht nur einmal ausgeführt wird. Nach dem Ende der aktuellen Schleife wird eine weitere Schleife ausgeführt, um zu überprüfen, ob Modelle geändert wurden. Dies ist eine schmutzige Überprüfung, die zum Umgang mit Modelländerungen verwendet wird, die auftreten können, wenn die Hörerfunktion ausgeführt wird. Daher wird die $ digest -Schleife weiter ausgeführt, bis sich das Modell nicht mehr ändert oder die $ Digest -Schleife 10 -mal erreicht. Versuchen Sie daher, das Modell in der Hörerfunktion nicht so weit wie möglich zu ändern.
HINWEIS: Die $ Digest -Schleife wird auch mindestens zweimal ausgeführt, auch wenn in der Hörerfunktion kein Modell geändert wird. Wie oben erläutert, wird es erneut ausgeführt, um sicherzustellen, dass sich die Modelle nicht ändern.
Abschluss
Das Wichtigste, an das Sie sich erinnern sollten, ist, ob AngularJs Ihre Modifikationen am Modell erkennen kann. Wenn es nicht erkannt werden kann, müssen Sie $ Apply () manuell anrufen.
Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Editor wird allen rechtzeitig antworten. Vielen Dank für Ihre Unterstützung auf der Wulin.com -Website!