Durch schmutziges Überprüfen des $scopeObjekts
Angular verwaltet eine einfache arrayAnzahl von Beobachtern in den $scopeObjekten. Wenn Sie eine inspizieren, werden $scopeSie feststellen, dass sie einen arrayangerufenen enthält $$watchers.
Jeder Beobachter ist ein object, der unter anderem enthält
- Ein Ausdruck, den der Beobachter überwacht. Dies könnte nur ein
attributeName 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
$scopeals 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 $watchein attributeein $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-modelanfordern, 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 $scopealler seiner Kinder . Für jeden $scope objectiterieren wir über seine $$watchers arrayund 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, $scopeist der verschmutzt
Wenn ein Beobachter ausgelöst wird, weiß die App, dass sich etwas geändert hat, und das $scopewird als verschmutzt markiert.
Watcher-Funktionen können andere Attribute auf $scopeoder auf einem übergeordneten Element ändern $scope. Wenn eine $watcherFunktion 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 $scopeBaum ü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 $digestschmutzig ist, führen wir das gesamte aus$digest Zyklus erneut aus
Wir durchlaufen den $digestZyklus 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 $scopeHierarchie, 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 $scopeBaum 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-repeatmit vielen Artikeln haben.
<div ng-repeat="person in people track by username">
{{::person.username}}
</div>