Heim > Artikel > Web-Frontend > Eine kurze Analyse des Lebenszyklus und der verzögerten Verarbeitung in AngularJS_AngularJS
Hier besprechen wir einige häufig verwendete erweiterte Inversion-of-Control-Container: Lazy-Loading, Lifetime-Management und verzögerte Erstellung/Verarbeitungsauflösung.
Lazy-Loading
Das sogenannte verzögerte Laden besteht darin, das Objekt zu instanziieren, wenn Sie es verwenden müssen. Viele Abhängigkeitsinjektionssysteme erstellen Komponenten von Anfang an als Abhängigkeiten. Manchmal möchten Sie diese Komponenten jedoch erst dann instanziieren, wenn Sie sie in Ihrer Anwendung verwenden. Ein gutes Beispiel in Angular ist, wenn Sie während der Konfiguration ein Verhalten festlegen und das Verhalten auf einige Komponenten verweist, die noch nicht erstellt wurden.
Angenommen, Sie möchten den integrierten $log-Dienst des Systems abfangen, also speichern Sie ihn in $rootScope. Natürlich empfehle ich das nicht, aber dieses Beispiel ist einfacher und effektiver. Zum Abfangen verwenden Sie während der Konfiguration $provide und rufen dann die geänderte Methode auf. Wenn Sie zu diesem Zeitpunkt direkt auf $rootScope verweisen möchten, erhalten Sie aufgrund des Zirkelverweises eine Ausnahme. Und die Lösung besteht darin, $rootScope über $injector verzögert zu laden.
Der folgende Code lädt $rootScope nur bei der ersten Verwendung.
$provide.decorator(, [, , ($delegate, $injector) { log = $delegate.log.bind($delegate); $delegate.log = (msg) { rs = $injector.get(); (rs.logs === undefined) { rs.logs = []; } rs.logs.push(msg); log(msg); }; $delegate; }]);
Folgende Aufrufe erhalten denselben Singleton $rootScope. Hier ist ein funktionierendes Beispiel. Ich habe anscheinend schon einmal eine (falsche) Aussage gehört (Angular unterstützt nur Singletons) ... Natürlich ist es nicht wahr. Die Methoden in $injector werden verwendet, um den Lebenszyklus Ihrer Komponenten für Sie zu verwalten.
Lebenszyklusmanagement
Der Lebenszyklus umfasst die Art und Weise, wie Sie Instanzen von Komponenten verwalten. Wenn Sie eine Angular-Abhängigkeit einfügen, erstellt Dependency Injection standardmäßig eine Kopie davon für Sie und verwendet sie in Ihrer Anwendung wieder. Meistens ist das genau das, was wir erwarten. In manchen Fällen sind mehrere Instanzen derselben Komponente erforderlich. Gehen Sie von folgendem Zähldienst aus:
Counter($log) { $log.log(); } angular.extend(Counter.prototype, { count: 0, increment: () { .count += 1; .count; } }); Counter.$inject = []; app.service(, Counter);
Ihre Anwendung verfolgt verschiedene Zähler. Und nachdem Sie den Dienst eingefügt haben, erhalten Sie immer den gleichen Zähler. Ist das eine Einschränkung von Angular?
Natürlich nicht. Auch hier können Sie jederzeit über den $injector-Dienst eine neue Kopie erstellen. Der folgende Code verwendet zwei unabhängige Zähler:
app.run([, , , (rs, c, i) { rs.count = c.count; rs.update = c.increment; rs.update2 = () { c = i.instantiate(Counter); rs.count2 = c.count; rs.update2 = () { c.increment(); rs.count2 = c.count; }; }; }]);
Sie können sehen, dass die Zähler von separaten Instanzen verfolgt werden. Hier ist ein brauchbares Beispiel. Wenn Sie häufig neue Instanzen generieren müssen, können Sie den Dienst wie folgt registrieren:
app.factory(, [, (i) { { getCounter: () { i.instantiate(Counter); } }; }]);
So einfach ist es, die erforderliche Instanz zu generieren, und Sie können stattdessen Ihre Factory-Komponente $injector:
verwenden
app.run([, , (rs, cf) { c1 = cf.getCounter(), c2 = cf.getCounter(); rs.count = c1.count; rs.update = c1.increment; rs.count2 = c2.count; rs.update2 = () { rs.count2 = c2.increment(); }; }]);
Sie können sich diese Vollversion des verfügbaren Beispiels ansehen. Wie Sie sehen, ist es durchaus möglich, den Lebenszyklus Ihrer Komponenten mithilfe der integrierten Abhängigkeitsinjektion von Angular zu verwalten. Was ist mit der verzögerten Auflösung – zum Beispiel gibt es Komponenten, die Sie einbinden müssen, nachdem Angular konfiguriert wurde, und die mit ihren Abhängigkeiten umschlossen werden müssen.
Aufgeschobene Lösung
Wir haben eine Möglichkeit eingeführt, Abhängigkeiten in Angular träge zu handhaben. Wenn Sie etwas umschließen möchten, können Sie die Instanziierung des $injector-Dienstes aufrufen und dieser kann dann die Abhängigkeit durch Parameter-Sniffing auflösen, was so aussieht, als würde er die statischen Eigenschaften von $inject verwenden, oder er kann dies auch durch Überprüfen tun Das Es ist als Array implementiert. Mit anderen Worten, das Folgende ist eine völlig gültige Schreibweise:
$injector.instantiate(['dependency', Constructor]);
Sie können Methoden auch für dekorierte Arrays aufrufen. Angenommen, Sie haben eine Methode, die vom $log-Dienst abhängt. Sie können sie zur Laufzeit mit verzögerter Verarbeitung aufrufen, etwa so:
myFunc = [, ($log) { $log.log(); }]; $injector.invoke(myFunc);
Sie können sich dieses Arbeitsbeispiel ansehen (öffnen Sie Ihre Konsole und sehen Sie, was passiert, nachdem Sie die Taste gedrückt haben).
Zusammenfassung
Zusammenfassend lässt sich sagen, dass die Abhängigkeitsinjektion von Angular viele erweiterte Funktionen bietet, die Sie in Ihrer Geschäftsanwendungsproduktionslinie benötigen und häufig verwenden. Die Bequemlichkeit von Fabriken, Diensten und Anbietern lässt Angular-Entwickler oft glauben, dass es nur eine Option gibt. Die Magie liegt im $injector-Dienst, mit dem Sie die benötigten Singletons generieren, neue Komponenten erstellen oder Methoden mit Abhängigkeiten dynamisch referenzieren können.
Beachten Sie abschließend, dass Injektionen in Ihren Client-Code auch außerhalb von Angular verfügbar sind. Schauen wir uns ein Beispiel für den Aufruf des $log-Dienstes durch Injektion außerhalb von Angular an. Klicken Sie hier. Warum müssen wir „ng“ an das Array der Methode übergeben? Es ist ein Kernmodul von Angular und wird implizit hinzugefügt, wenn Sie Ihr Modul umschließen. Wenn Ihre Direktive jedoch eine eigene injizierte Instanz generiert, müssen Sie sie explizit hinzufügen.