Mit AngularJS können Sie eine bidirektionale Datenbindung implementieren. Der interessante Teil ist jedoch, wie er Modelländerungen erkennt? Das Modell ist normalerweise ein einfaches Objekt wie der folgende Code. Wir können die name-Eigenschaft von $scope.user
ändern, aber wie erkennt AngularJS das Modell? Zeigt AngularJS alle Eigenschaften des Objekts $scope
an?
Es gibt einen Digest-Zyklus, in dem der Bereich alle $ watch-Ausdrücke untersucht und sie mit dem vorherigen Wert vergleicht. Wenn der alte Wert nicht mit dem neuen Wert übereinstimmt, wird AngularJS die entsprechenden Stellen aktualisieren, a.k.a dreckige Prüfung.
Damit der Digest-Zyklus ausgeführt werden kann, muss $apply(fn)
ausgeführt werden. So gelangen Sie in die Angular-Welt von JavaScript. Wie wird $apply(fn)
aufgerufen (aus AngularJs Integration mit dem Browser ) ):
Erläuterung des Auswertungszyklus
Um eine bidirektionale Bindung zu erreichen, registrieren Direktiven Beobachter. Damit eine Seite schnell und effizient ist, müssen wir versuchen, alle diese von uns erstellten Beobachter zu reduzieren. Sie sollten also vorsichtig sein, wenn Sie eine Zweiwege-Bindung verwenden - d. H. Verwenden Sie sie nur, wenn Sie sie wirklich benötigen. Ansonsten Einweg verwenden:
<h1> {{ ::vm.title }} </h1>
Hier ist es ziemlich offensichtlich, dass der Titel der Seite wahrscheinlich nicht geändert wird, während sich der Benutzer auf der Seite befindet - oder er muss den neuen sehen, wenn er geändert wird. So können wir ::
verwenden, um eine unidirektionale Bindung während der Template-Verknüpfungsphase zu registrieren.
Die Hauptprobleme, die ich bei Explosionen von Beobachtern gesehen habe, sind Gitter mit Hunderten von Reihen. Wenn diese Zeilen ziemlich viele Spalten haben und in jeder Zelle eine Zweiwege-Datenbindung besteht, dann ist es ein Vergnügen. Sie können sich zurücklehnen und warten, bis die Seite geladen ist!
Zwei-Wege-Bindung beschränkt sich fast ausschließlich auf Elemente, die ng-model
verwenden. Die Richtung, die von Ansicht zu Modell geht, verwendet Standard-Event-Handler, um Änderungen zu erkennen, die innerhalb des Modells aktualisiert werden müssen (z. B. onchange
). Die Richtung vom Modell zurück zur Ansicht wird während eines $digest
aktualisiert. Aber wir rufen $digest
nicht direkt auf.
Jedes Element auf Ihrer Seite, das auf den Digest-Zyklus reagiert, fügt irgendwo einen Listener und einen Ausdruck an seinen Bereich mit $watch
an. Wenn Sie {{ foo() }}
schreiben oder ng-model='user.name'
verwenden, wird intern ein Aufruf von $watch
in Ihrem Namen mit einem Javascript-Ausdruck aufgerufen, der jedes Mal ausgeführt wird, wenn ein Digest-Zyklus ausgeführt wird. Diese Registrierung kann während der Kompilierung der Vorlage (unserem ersten Beispiel) oder während der Linkphase einer Direktive (unserer zweiten) erfolgen.
Hier gibt es keine Magie. Die angehängten Listener sind reguläre Funktionen - in unserem Beispiel wird der Listener für den Ausdruck foo()
bereitgestellt und der HTML-Text auf der Seite aktualisiert, während der Listener für den Ausdruck user.name
% aufruft. co_de% oder setText
oder was auch immer von der bestimmten Eingabe verlangt wird, an die setOption
angehängt wurde.
Obwohl eckig die meisten Abhörmaßnahmen bewältigen kann, können Sie Ihre eigenen Abhörmusik mit Ihren eigenen Zuhörern manuell in jeder Funktion mit Zugriff auf einen Bereich anhängen (der Bereich ist wichtig, da wir diese Beobachter abreißen, wenn die entsprechenden Teile der Seite werden entfernt). Achte auf den Überschuss. Bindungen sind nicht frei und je mehr Dinge gebunden sind, desto langsamer reagiert die Seite. Einmalige Bindungen sind eine Möglichkeit, diese Kosten zu reduzieren. Die Verwendung von ng-model
mit $on
und $emit
ist ein weiteres.
Also wann heißt Digest? Es ist sicherlich nicht automatisch. Wenn der Digest-Zyklus ausgeführt wird, bedeutet dies, dass irgendwo in ihrem Bereich oder im Stammbereich ein Name namens $broadcast
steht. $apply
fügt Handler hinzu, die auf normale HTML-Ereignisse reagieren und in Ihrem Auftrag Aufrufe von ng-model
vornehmen. Aber $apply
, auf der anderen Seite, wird niemals aufgerufen werden, bis irgendwo ein anderes Skript irgendwo foo()
aufruft. Glücklicherweise füllen die meisten Funktionen, die Sie für eckigen Zeilenumbruch ausfüllen, diese Funktionen mit einem Aufruf von $apply
, so dass Sie den Aufruf nicht oft selbst durchführen müssen (zB $apply
wird mit $timeout
umschlossen, weshalb wir benutze es anstelle von $apply
). Wenn Sie jedoch etwas außerhalb des Bereichs von angular verwenden (eine Bibliothek von Drittanbietern, die sich mit Ereignissen verbindet), müssen Sie daran denken, setTimeout
selbst aufzurufen, und wie oben können Sie dies manuell tun, indem Sie $apply
aufrufen. überall, wo Sie Zugriff auf einen Bereich haben.
Um die Datenbindung zu ermöglichen, verwendet AngularJS $ watch-APIs, um die Änderungen am Bereich zu beobachten. AngularJS registrierte Beobachter für jede Variable im Bereich, um den Wert darin zu beobachten. Wenn der Wert der Variablen im Bereich geändert wird, wird die Ansicht automatisch aktualisiert.
Es passiert, weil der $ Digest-Zyklus ausgelöst wird. Daher verarbeitet AngularJS alle registrierten Beobachter des aktuellen Bereichs und der untergeordneten Elemente und sucht nach den Aktualisierungen und ruft die dedizierten Überwachungslistener auf, bis das Modell stabilisiert ist und keine weiteren Listener ausgelöst werden. Sobald die $ digest-Schleife die Ausführung beendet hat, rendert der Browser das DOM erneut und spiegelt die Änderungen wider.
Standardmäßig wird jede Variable in einem Bereich durch den Winkel beobachtet. Auf diese Weise werden unnötige Variablen auch durch den Winkel beobachtet, was zeitaufwendig ist und als Ergebnis dazu führt, dass die Seite langsam wird.
Tags und Links angularjs 2-way-object-databinding