Di sini, kami membincangkan beberapa bekas Penyongsangan Kawalan termaju yang biasa digunakan: pemuatan malas, pengurusan seumur hidup dan resolusi penciptaan/pemprosesan tertunda).
Malas-Memuat
Apa yang dipanggil pemuatan malas adalah untuk membuat seketika objek apabila anda perlu menggunakannya. Banyak sistem suntikan kebergantungan mencipta komponen sebagai kebergantungan dari awal. Tetapi kadangkala, anda tidak mahu membuat instantiate komponen ini sehingga anda menggunakannya dalam aplikasi anda. Dalam Angular, contoh yang baik ialah apabila anda menetapkan tingkah laku semasa konfigurasi, dan tingkah laku itu merujuk kepada beberapa komponen yang belum dibuat lagi.
Andaikan anda ingin memintas perkhidmatan $log terbina dalam sistem, jadi anda menyimpannya dalam $rootScope. Sudah tentu saya tidak mengesyorkan ini, tetapi contoh ini lebih mudah dan lebih berkesan. Untuk memintas, anda menggunakan $provide semasa konfigurasi dan kemudian memanggil kaedah yang diubah suai. Jika anda ingin merujuk $rootScope secara langsung pada masa ini, anda akan mendapat pengecualian kerana rujukan pekeliling. Dan penyelesaiannya ialah dengan malas memuatkan $rootScope melalui $injector .
Kod berikut hanya akan memuatkan $rootScope pada kali pertama ia digunakan.
$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; }]);
Panggilan berikut akan mendapat $rootScope tunggal yang sama. Berikut ialah contoh yang berkesan. Saya nampaknya pernah mendengar kenyataan (salah) sebelum ini (Angular hanya menyokong singleton)... Sudah tentu ia tidak benar. Kaedah dalam $injector digunakan untuk menguruskan kitaran hayat komponen anda untuk anda.
Pengurusan kitaran hayat
Kitaran hayat melibatkan cara anda mengurus kejadian komponen. Secara lalai, apabila anda menyuntik kebergantungan Sudut, Suntikan Ketergantungan akan mencipta salinannya untuk anda dan menggunakannya semula dalam aplikasi anda. Selalunya ini adalah apa yang kita jangkakan. Dalam sesetengah kes, berbilang contoh komponen yang sama diperlukan. Andaikan perkhidmatan mengira berikut:
Counter($log) { $log.log(); } angular.extend(Counter.prototype, { count: 0, increment: () { .count += 1; .count; } }); Counter.$inject = []; app.service(, Counter);
Aplikasi anda akan menjejaki kaunter yang berbeza. Dan selepas anda menyuntik perkhidmatan, anda akan sentiasa mendapat kaunter yang sama. Adakah ini batasan Angular?
Sudah tentu tidak. Sekali lagi, anda boleh membuat salinan baharu pada bila-bila masa melalui perkhidmatan $injector. Kod berikut menggunakan dua pembilang bebas:
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; }; }; }]);
Anda boleh melihat bahawa kaunter dijejaki oleh kejadian yang berasingan, berikut ialah contoh yang boleh digunakan. Jika anda perlu menjana kejadian baharu dengan kerap, anda boleh mendaftarkan perkhidmatan seperti ini:
app.factory(, [, (i) { { getCounter: () { i.instantiate(Counter); } }; }]);
Semudah itu untuk menjana contoh yang diperlukan, dan anda boleh menggunakan komponen kilang anda sebagai ganti $injector:
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(); }; }]);
Anda boleh menyemak ini versi penuh contoh yang tersedia. Seperti yang anda lihat, adalah mustahil untuk menguruskan kitaran hayat komponen anda menggunakan suntikan pergantungan terbina dalam Angular. Bagaimana pula dengan resolusi tertunda - contohnya, terdapat komponen yang anda perlu bawa masuk selepas Angular telah dikonfigurasikan, dan perlu dibalut dengan kebergantungan mereka.
Resolusi Tertunda
Kami telah memperkenalkan cara untuk mengendalikan kebergantungan dengan malas dalam Angular. Apabila anda ingin membungkus sesuatu, anda boleh memanggil instantiate perkhidmatan $injector, dan ia kemudian boleh menyelesaikan kebergantungan dengan parameter menghidu, yang kelihatan seperti ia akan menggunakan sifat statik $inject, atau ia juga boleh melakukannya dengan memeriksa yang Ia dilaksanakan sebagai tatasusunan. Dalam erti kata lain, berikut ialah cara penulisan yang sah sepenuhnya:
$injector.instantiate(['dependency', Constructor]);
Anda juga boleh memanggil kaedah pada tatasusunan berhias. Katakan anda mempunyai kaedah yang bergantung pada perkhidmatan $log Anda boleh memanggilnya pada masa jalan dengan pemprosesan tertunda, seperti ini:
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.