Saya memiliki satu set komponen angular2 yang semuanya harus mendapatkan layanan yang disuntikkan. Pikiran pertama saya adalah yang terbaik adalah membuat kelas super dan memasukkan layanan di sana. Salah satu komponen saya kemudian akan memperluas superclass itu tetapi pendekatan ini tidak berhasil.
Contoh yang disederhanakan:
export class AbstractComponent {
constructor(private myservice: MyService) {
// Inject the service I need for all components
}
}
export MyComponent extends AbstractComponent {
constructor(private anotherService: AnotherService) {
super(); // This gives an error as super constructor needs an argument
}
}
Saya bisa menyelesaikan ini dengan menyuntikkan MyService
dalam setiap komponen dan menggunakan argumen itu untuk super()
panggilan tetapi itu pasti semacam tidak masuk akal.
Bagaimana cara mengatur komponen saya dengan benar sehingga mereka mewarisi layanan dari kelas super?
new MyService()
alih-alih menyuntikkan memberi Anda hasil yang persis sama (kecuali lebih efisien). Jika Anda ingin berbagi contoh layanan yang sama di berbagai layanan dan / atau komponen, ini tidak akan berfungsi. Setiap kelas akan mendapatkanMyService
contoh lain .myService
. Menemukan solusi yang menghindari hal ini tetapi menambahkan lebih banyak kode ke kelas turunan ...Jawaban:
Itu tidak masuk akal. Ini adalah cara kerja konstruktor dan injeksi konstruktor.
Setiap kelas yang dapat diinjeksi harus mendeklarasikan dependensi sebagai parameter konstruktor dan jika superclass juga memiliki dependensi, ini juga perlu dicantumkan dalam konstruktor subclass dan diteruskan ke superclass dengan
super(dep1, dep2)
panggilan tersebut.Meneruskan injektor dan memperoleh ketergantungan sangat penting memiliki kerugian yang serius.
Ini menyembunyikan dependensi yang membuat kode lebih sulit dibaca.
Itu melanggar ekspektasi orang yang akrab dengan cara kerja Angular2 DI.
Ini merusak kompilasi offline yang menghasilkan kode statis untuk menggantikan DI deklaratif dan imperatif untuk meningkatkan kinerja dan mengurangi ukuran kode.
sumber
super
panggilan yang sesuai ) ke sekitar 20+ kelas dan jumlah itu hanya akan bertambah di masa depan. Jadi dua hal: 1) Saya tidak suka melihat "basis kode besar" melakukan ini; dan 2) Terima kasih Tuhan untuk vimq
dan vscodectrl+.
Solusi yang diperbarui, mencegah beberapa contoh myService dibuat dengan menggunakan injektor global.
Ini akan memastikan bahwa MyService dapat digunakan dalam semua kelas yang memperluas AbstractComponent tanpa perlu memasukkan MyService di setiap kelas turunan.
Ada beberapa kontra untuk solusi ini (lihat Komentar dari @ Günter Zöchbauer di bawah pertanyaan asli saya):
Untuk penjelasan yang ditulis dengan sangat baik tentang injeksi ketergantungan di Angular2 lihat posting blog ini yang sangat membantu saya untuk menyelesaikan masalah: http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular- 2.html
sumber
this.myServiceA = injector.get(MyServiceA);
dll?Injector
secara global untuk menghindari keharusan merantai parameter apa punAbstractComponent
? fwiw, saya pikir properti menyuntikkan dependensi ke kelas dasar yang banyak digunakan untuk menghindari rangkaian konstruktor yang berantakan adalah pengecualian yang benar-benar valid untuk aturan biasa.Alih-alih memasukkan semua layanan secara manual, saya membuat kelas yang menyediakan layanan, misalnya, ia mendapatkan layanan yang disuntikkan. Kelas ini kemudian dimasukkan ke dalam kelas turunan dan diteruskan ke kelas dasar.
Kelas turunan:
Kelas dasar:
Kelas penyedia layanan:
sumber
Daripada memasukkan layanan yang memiliki semua layanan lain sebagai dependensi, seperti:
Saya akan melewatkan langkah ekstra ini dan cukup menambahkan suntikan semua layanan di BaseComponent, seperti:
Teknik ini mengasumsikan 2 hal:
Perhatian Anda sepenuhnya terkait dengan pewarisan komponen. Kemungkinan besar, alasan Anda mendapatkan pertanyaan ini adalah karena banyaknya kode non-dry (WET?) Yang perlu Anda ulangi di setiap kelas turunan. Jika Anda ingin memanfaatkan satu titik masuk untuk semua komponen dan layanan Anda, Anda perlu melakukan langkah tambahan.
Setiap komponen memperluas
BaseComponent
Ada juga kerugiannya jika Anda memutuskan untuk menggunakan konstruktor dari kelas turunan, karena Anda perlu memanggil
super()
dan meneruskan semua dependensi. Meskipun saya tidak benar-benar melihat kasus penggunaan yang mengharuskan penggunaanconstructor
alih-alihngOnInit
, sangat mungkin bahwa kasus penggunaan seperti itu ada.sumber
Dari apa yang saya pahami untuk mewarisi dari kelas dasar, pertama-tama Anda harus membuat instance-nya. Untuk membuatnya, Anda perlu meneruskan parameter yang diperlukan konstruktornya sehingga Anda meneruskannya dari anak ke orang tua melalui panggilan super () sehingga masuk akal. Injector tentu saja adalah solusi lain yang layak.
sumber
Jika kelas induk telah didapat dari plugin pihak ketiga (dan Anda tidak dapat mengubah sumbernya), Anda dapat melakukan ini:
atau cara yang paling baik (tetap hanya satu parameter dalam konstruktor):
sumber
HACK JELEK
Beberapa waktu lalu beberapa klien saya ingin bergabung dengan dua proyek sudut BESAR sampai kemarin (sudut v4 ke sudut v8). Project v4 menggunakan kelas BaseView untuk setiap komponen dan berisi
tr(key)
metode terjemahan (di v8 saya menggunakan ng-translate). Jadi untuk menghindari mengganti sistem terjemahan dan mengedit ratusan template (di v4) atau menyiapkan 2 sistem terjemahan secara paralel, saya menggunakan peretasan jelek berikut (saya tidak bangga) - diAppModule
kelas saya menambahkan konstruktor berikut:dan sekarang
AbstractComponent
Anda bisa menggunakansumber