Durch schmutziges Überprüfen des $scope
Objekts
Angular verwaltet eine einfache array
Anzahl von Beobachtern in den $scope
Objekten. Wenn Sie eine inspizieren, werden $scope
Sie feststellen, dass sie einen array
angerufenen enthält $$watchers
.
Jeder Beobachter ist ein object
, der unter anderem enthält
- Ein Ausdruck, den der Beobachter überwacht. Dies könnte nur ein
attribute
Name oder etwas Komplizierteres sein.
- Ein letzter bekannter Wert des Ausdrucks. Dies kann mit dem aktuell berechneten Wert des Ausdrucks verglichen werden. Wenn sich die Werte unterscheiden, löst der Beobachter die Funktion aus und markiert sie
$scope
als verschmutzt.
- Eine Funktion, die ausgeführt wird, wenn der Watcher verschmutzt ist.
Wie Beobachter definiert werden
Es gibt viele verschiedene Möglichkeiten, einen Beobachter in AngularJS zu definieren.
Sie können explizit $watch
ein attribute
ein $scope
.
$scope.$watch('person.username', validateUnique);
Sie können eine {{}}
Interpolation in Ihre Vorlage einfügen (ein Beobachter wird aktuell für Sie erstellt $scope
).
<p>username: {{person.username}}</p>
Sie können eine Anweisung ng-model
anfordern, um den Beobachter für Sie zu definieren.
<input ng-model="person.username" />
Das $digest
Zyklus prüft alle Beobachter auf ihren letzten Wert
Wenn wir mit AngularJS über die normalen Kanäle (ng-model, ng-repeat usw.) interagieren, wird durch die Direktive ein Digest-Zyklus ausgelöst.
Ein Verdauungszyklus ist eine Tiefenüberquerung $scope
aller seiner Kinder . Für jeden $scope
object
iterieren wir über seine $$watchers
array
und bewerten alle Ausdrücke. Wenn sich der neue Ausdruckswert vom letzten bekannten Wert unterscheidet, wird die Watcher-Funktion aufgerufen. Diese Funktion kann einen Teil des DOM neu kompilieren, einen Wert für neu berechnen $scope
, einen auslösen AJAX
request
, alles, was Sie dazu benötigen.
Jeder Bereich wird durchlaufen und jeder Überwachungsausdruck wird ausgewertet und mit dem letzten Wert verglichen.
Wenn ein Beobachter ausgelöst wird, $scope
ist der verschmutzt
Wenn ein Beobachter ausgelöst wird, weiß die App, dass sich etwas geändert hat, und das $scope
wird als verschmutzt markiert.
Watcher-Funktionen können andere Attribute auf $scope
oder auf einem übergeordneten Element ändern $scope
. Wenn eine $watcher
Funktion ausgelöst wurde, können wir nicht garantieren, dass unsere andere$scope
noch sauber sind, und führen daher den gesamten Digest-Zyklus erneut aus.
Dies liegt daran, dass AngularJS über eine bidirektionale Bindung verfügt, sodass Daten wieder in den $scope
Baum übertragen werden können. Wir können einen Wert auf einem höheren Wert ändern $scope
, der bereits verdaut wurde. Vielleicht ändern wir einen Wert auf der $rootScope
.
Wenn das $digest
schmutzig ist, führen wir das gesamte aus$digest
Zyklus erneut aus
Wir durchlaufen den $digest
Zyklus kontinuierlich, bis entweder der Verdauungszyklus sauber ist (alles$watch
Ausdrücke haben den gleichen Wert wie im vorherigen Zyklus) oder wir das Digest-Limit erreichen. Standardmäßig ist diese Grenze auf 10 festgelegt.
Wenn wir das Digest-Limit erreichen, wird AngularJS einen Fehler in der Konsole auslösen:
10 $digest() iterations reached. Aborting!
Der Digest ist hart für die Maschine, aber für den Entwickler einfach
Wie Sie sehen können, überprüft AngularJS jedes Mal, wenn sich in einer AngularJS-App etwas ändert, jeden einzelnen Beobachter in der $scope
Hierarchie, um zu sehen, wie er reagieren soll. Für einen Entwickler ist dies ein enormer Produktivitätsvorteil, da Sie jetzt fast keinen Verkabelungscode mehr schreiben müssen. AngularJS merkt nur, wenn sich ein Wert geändert hat, und macht den Rest der App mit der Änderung konsistent.
Aus Sicht der Maschine ist dies jedoch äußerst ineffizient und verlangsamt unsere App, wenn wir zu viele Beobachter erstellen. Misko hat eine Zahl von ungefähr 4000 Beobachtern angegeben, bevor sich Ihre App in älteren Browsern langsam anfühlt.
Diese Grenze ist leicht zu erreichen, wenn Sie ng-repeat
über eine großeJSON
array
zum Beispiel . Sie können dem entgegenwirken, indem Sie Funktionen wie die einmalige Bindung zum Kompilieren einer Vorlage verwenden, ohne Beobachter zu erstellen.
So vermeiden Sie, dass zu viele Beobachter erstellt werden
Jedes Mal, wenn Ihr Benutzer mit Ihrer App interagiert, wird jeder einzelne Beobachter in Ihrer App mindestens einmal bewertet. Ein großer Teil der Optimierung einer AngularJS-App besteht darin, die Anzahl der Beobachter in Ihrem $scope
Baum zu reduzieren . Eine einfache Möglichkeit, dies zu tun, ist die einmalige Bindung .
Wenn Sie Daten haben, die sich selten ändern, können Sie sie nur einmal mit der :: -Syntax binden, wie folgt:
<p>{{::person.username}}</p>
oder
<p ng-bind="::person.username"></p>
Die Bindung wird nur ausgelöst, wenn die enthaltene Vorlage gerendert und die Daten geladen wurden $scope
.
Dies ist besonders wichtig, wenn Sie eine ng-repeat
mit vielen Artikeln haben.
<div ng-repeat="person in people track by username">
{{::person.username}}
</div>