Was genau ist Change Detection?
Um es auf den Punkt zu bringen: Angular muss verfolgen, wann sich Dinge in deiner Anwendung ändern. Nehmen wir an, wir haben ein Member in der Klasse für unsere Komponente:name lautet zunächst Levin und wird im Template angezeigt. Wir haben jedoch einen Button, der beim Klicken die Methode changeName auslöst, wodurch dieser Wert Kathy geändert wird.
Wenn du auf den Button klickst, wirst du wahrscheinlich nicht überrascht sein, dass sich der im Template angezeigte Wert ändert. Das ist genau das, was wir erreichen wollen, aber die zugrunde liegenden Mechanismen, mit denen Angular diese scheinbar einfache Aufgabe erfüllt, sind gar nicht so einfach.
Wir könnten das Template auch auf andere Weise ändern – wie wäre es mit einem setTimeout, das die Änderung nach 2 Sekunden auslöst?
Wir verwenden hier einen der Lifecycle-Hooks von Angular, um beim Initialisieren der Komponente einen bestimmten Code auszuführen. Es gibt auch andere Lifecycle-Hooks von Angular, wie
OnDestroy und AfterViewInit.setInterval, das den Wert jede Sekunde ändert:
Wie erkennt Angular Änderungen?
Wir werden nicht näher auf die genauen Mechanismen eingehen, die es Angular ermöglichen, Änderungen zu erkennen und darauf zu reagieren. Dies kann für die Leistungsoptimierung nützlich sein, aber darauf müssen wir jetzt nicht näher eingehen. Unser Hauptziel ist es, den Unterschied zwischen derDefault Change Detection Strategie und der OnPush Change Detection Strategie zu verstehen. Dazu müssen wir ein wenig über die Funktionsweise der Standard Change Detection Strategie wissen.
Der Schlüssel dazu liegt darin, dass Angular mithilfe von Zone.js erkennt, wann Code ausgeführt wird, der eine Änderung verursachen könnte. Zu den Szenarien, die eine Änderung des Status deiner Anwendung verursachen können, gehören:
- Initialisierung von Komponenten
- Ausgelöste Ereignisse (wie unser Button-Klick von zuvor)
- Verarbeitung der Antwort einer HTTP-Anfrage
- Macro Tasks wie
setTimeout()undsetInterval() - Micro Tasks wie die Verarbeitung von Promises
Die OnPush-Strategie
Sehen wir uns nun an, wie sich die OnPush Change Detection Strategie vom Standard unterscheidet. Wir werden alle unsere Beispiele von zuvor noch einmal durchgehen, aber dieses Mal werden wir die Komponente so aktualisieren, dass sie die OnPush-Änderungserkennung verwendet:
- Event
- Timeout
- Interval
OnPush-Änderungserkennungsstrategie einige Regeln hinzufügt, die festlegen, was dazu führen kann, dass eine Komponente während der Änderungserkennung auf Änderungen überprüft wird. Bei der Standardstrategie muss Angular auf jede mögliche Änderung reagieren, während wir mit OnPush Angular sozusagen mitteilen können, dass es diese Komponente nur unter bestimmten Umständen auf Änderungen überprüfen muss. Das bedeutet, dass Angular viel weniger Überprüfungsarbeit zu erledigen hat.
Die Möglichkeiten, wie eine Komponente, die die OnPush-Änderungserkennungsstrategie verwendet, während der Change Detection zur Überprüfung markiert werden kann, sind:
Event
Event
Der Event-Handler einer Komponente wird innerhalb der Komponente ausgelöst, z. B.:Wenn
(click) oder andere Event Bindings ausgelöst werden, wird die Änderungserkennung ausgelöst. Wir haben dies bereits gesehen, da es unser einziges Beispiel ist, das noch funktioniert.Inputs
Inputs
Die Inputs einer Komponente haben sich geändert, z. B.:Wenn sich der Wert von
someValue ändert, wird eine Change Detection für die Komponente und alle übergeordneten Komponenten bis zur Root-Komponente ausgelöst.`async`-Pipe
`async`-Pipe
Die
async-Pipe wird im Template verwendet, und der Stream/das Promise, auf das sie angewendet wird, gibt einen Wert aus:Obwohl normalerweise die
async-Pipe verwendet wird, um diese Komponente für die Änderungserkennung zu markieren, ist es tatsächlich die markForCheck-Funktion, die die async-Pipe im Hintergrund verwendet, die diese Aufgabe übernimmt (und auch andere Dinge ausser der async-Pipe könnten dieselbe Technik verwenden, um eine OnPush-Komponente zu markieren, die während der Änderungserkennung überprüft werden soll).ChangeDetectorRef manuell einzufügen und die Änderungserkennung selbst auszulösen, aber dies sollte generell vermieden werden und nur als letzter Ausweg betrachtet werden.
Dies ist zwar wesentlich restriktiver, erhöht jedoch die Leistung und bietet uns einen noch grösseren Vorteil.