Saya ingin membuat ekstensi untuk beberapa komponen yang sudah digunakan di Angular 2, tanpa harus menulis ulang mereka hampir sepenuhnya, karena komponen dasar dapat mengalami perubahan dan berharap perubahan ini juga tercermin dalam komponen turunannya.
Saya membuat contoh sederhana ini untuk mencoba menjelaskan pertanyaan saya dengan lebih baik:
Dengan komponen dasar berikut app/base-panel.component.ts
:
import {Component, Input} from 'angular2/core';
@Component({
selector: 'base-panel',
template: '<div class="panel" [style.background-color]="color" (click)="onClick($event)">{{content}}</div>',
styles: [`
.panel{
padding: 50px;
}
`]
})
export class BasePanelComponent {
@Input() content: string;
color: string = "red";
onClick(event){
console.log("Click color: " + this.color);
}
}
Apakah Anda ingin membuat komponen turunan lain hanya alter, misalnya, perilaku komponen dasar dalam kasus contoh warna, app/my-panel.component.ts
:
import {Component} from 'angular2/core';
import {BasePanelComponent} from './base-panel.component'
@Component({
selector: 'my-panel',
template: '<div class="panel" [style.background-color]="color" (click)="onClick($event)">{{content}}</div>',
styles: [`
.panel{
padding: 50px;
}
`]
})
export class MyPanelComponent extends BasePanelComponent{
constructor() {
super();
this.color = "blue";
}
}
Contoh kerja lengkap di Plunker
Catatan: Jelas contoh ini sederhana dan dapat diselesaikan jika tidak perlu menggunakan warisan, tetapi ini dimaksudkan hanya untuk menggambarkan masalah sebenarnya.
Seperti yang Anda lihat dalam implementasi komponen turunan app/my-panel.component.ts
, banyak implementasi diulangi, dan satu bagian yang benar-benar diwariskan adalah class
BasePanelComponent
, tetapi pada @Component
dasarnya harus diulangi sepenuhnya, bukan hanya bagian yang diubah, seperti selector: 'my-panel'
.
Apakah ada cara untuk membuat warisan penuh komponen Angular2, yang mewarisi class
definisi tanda / anotasi, misalnya @Component
?
Sunting 1 - Permintaan Fitur
Permintaan fitur angular2 ditambahkan ke proyek di GitHub: Memperpanjang / Mewarisi komponen angular2 penjelasan # 7968
Sunting 2 - Permintaan Tertutup
Permintaan ditutup, karena alasan ini , bahwa sebentar tidak akan tahu bagaimana menggabungkan dekorator yang akan dibuat. Meninggalkan kami tanpa opsi. Jadi pendapat saya dikutip dalam Issue .
sumber
Jawaban:
Solusi alternatif:
Jawaban Thierry Templier ini adalah cara alternatif untuk menyelesaikan masalah.
Setelah beberapa pertanyaan dengan Thierry Templier, saya sampai pada contoh kerja berikut yang memenuhi harapan saya sebagai alternatif pembatasan warisan yang disebutkan dalam pertanyaan ini:
1 - Buat dekorator khusus:
2 - Komponen Dasar dengan dekorator @Component:
3 - Sub komponen dengan dekorator @CustomComponent:
Plunkr dengan contoh lengkap.
sumber
Angular 2 versi 2.3 baru saja dirilis, dan itu termasuk warisan komponen asli. Sepertinya Anda dapat mewarisi dan menimpa apa pun yang Anda inginkan, kecuali untuk template dan gaya. Beberapa referensi:
Fitur baru di Angular 2.3
Komponen Warisan dalam Angular 2
Plunkr mendemonstrasikan pewarisan komponen
sumber
More than one component matched on this element
jika Anda tidak.@Component()
tag. Tapi, Anda bisa membagikan .html atau .css dengan merujuk ke file yang sama jika Anda mau. Semua dalam semua, ini merupakan nilai tambah besar .Sekarang TypeScript 2.2 mendukung Mixin melalui ekspresi Kelas, kami memiliki cara yang jauh lebih baik untuk mengekspresikan Mixin pada Komponen. Perlu diketahui bahwa Anda juga dapat menggunakan warisan Komponen sejak sudut 2.3 ( diskusi ) atau dekorator khusus seperti yang dibahas dalam jawaban lain di sini. Namun, saya pikir Mixin memiliki beberapa properti yang membuatnya lebih disukai untuk menggunakan kembali perilaku di seluruh komponen:
Saya sangat menyarankan Anda membaca pengumuman TypeScript 2.2 di atas untuk memahami cara kerja Mixins. Diskusi terkait dalam masalah sudut GitHub memberikan detail tambahan.
Anda membutuhkan jenis-jenis ini:
Dan kemudian Anda dapat mendeklarasikan Mixin seperti ini
Destroyable
mixin yang membantu komponen melacak langganan yang perlu dibuang dingOnDestroy
:Untuk mencampur
Destroyable
menjadiComponent
, Anda mendeklarasikan komponen Anda seperti ini:Perhatikan bahwa
MixinRoot
hanya diperlukan ketika Anda inginextend
komposisi Mixin. Anda dapat dengan mudah memperluas beberapa mixins misalnyaA extends B(C(D))
. Ini adalah linierisasi yang jelas dari mixin yang saya bicarakan di atas, misalnya Anda secara efektif menyusun hierarki warisanA -> B -> C -> D
.Dalam kasus lain, misalnya ketika Anda ingin membuat Mixin pada kelas yang ada, Anda dapat menerapkan Mixin seperti:
Namun, saya menemukan cara pertama bekerja paling baik untuk
Components
danDirectives
, karena ini juga perlu dihiasi@Component
atau@Directive
tetap.sumber
function Destroyable<T extends Constructor<{}>>(Base = class { } as T)
. Dengan begitu saya bisa membuat mixin menggunakanextends Destroyable()
.memperbarui
Pewarisan komponen didukung sejak 2.3.0-rc.0
asli
Sejauh ini, yang paling nyaman bagi saya adalah untuk menjaga template & style menjadi file
*html
& terpisah*.css
dan tentukan melaluitemplateUrl
danstyleUrls
, jadi mudah digunakan kembali.sumber
@Input()
dan@Output()
dekorator, bukan?Sejauh yang saya tahu komponen inheritance belum diimplementasikan di Angular 2 dan saya tidak yakin apakah mereka memiliki rencana untuk melakukannya, namun karena Angular 2 menggunakan skrip (jika Anda memutuskan untuk menggunakan rute itu), Anda dapat menggunakan pewarisan kelas dengan melakukan
class MyClass extends OtherClass { ... }
. Untuk pewarisan komponen, saya sarankan untuk terlibat dengan proyek Angular 2 dengan membuka https://github.com/angular/angular/issues dan mengirimkan permintaan fitur!sumber
export class MyPanelComponent extends BasePanelComponent
), masalahnya hanya dalam kasus Anotasi / Dekorator yang tidak diwariskan.@SubComponent()
) yang menandai kelas sebagai subkomponen atau memiliki bidang tambahan pada@Component
dekorator yang memungkinkan Anda untuk referensi komponen induk untuk diwarisi.Mari kita pahami beberapa batasan & fitur utama pada sistem pewarisan komponen Angular.
Komponen hanya mewarisi logika kelas:
Fitur-fitur ini sangat penting untuk diingat, jadi mari kita periksa masing-masing secara mandiri.
Komponen hanya mewarisi logika kelas
Saat Anda mewarisi Komponen, semua logika di dalamnya sama-sama diwarisi. Perlu dicatat bahwa hanya anggota publik yang diwarisi karena anggota pribadi hanya dapat diakses di kelas yang mengimplementasikannya.
Semua meta-data di dekorator @Component tidak diwariskan
Fakta bahwa tidak ada meta-data yang diwariskan mungkin tampak kontra-intuitif pada awalnya tetapi, jika Anda berpikir tentang hal ini sebenarnya masuk akal. Jika Anda mewarisi dari Component say (componentA), Anda tidak ingin pemilih ComponentA, yang Anda warisi untuk menggantikan pemilih ComponentB yang merupakan kelas yang mewarisi. Hal yang sama dapat dikatakan untuk template / templateUrl serta style / styleUrls.
Properti Component @Input dan @Output diwarisi
Ini adalah fitur lain yang sangat saya sukai tentang komponen Inheritance in Angular. Dalam kalimat sederhana, setiap kali Anda memiliki properti @Input dan @Output khusus, properti ini akan diwarisi.
Daur hidup komponen tidak diwarisi
Bagian ini adalah salah satu yang tidak begitu jelas terutama bagi orang-orang yang belum banyak bekerja dengan prinsip-prinsip OOP. Misalnya, Anda memiliki ComponentA yang mengimplementasikan salah satu dari banyak kait siklus hidup Angular seperti OnInit. Jika Anda membuat ComponentB dan mewarisi ComponentA, siklus hidup OnInit dari ComponentA tidak akan aktif hingga Anda menyebutnya secara eksplisit bahkan jika Anda memiliki siklus hidup OnInit untuk ComponentB.
Memanggil Metode Komponen Super / Base
Untuk mendapatkan metode ngOnInit () dari ComponentA fire, kita perlu menggunakan kata kunci super dan memanggil metode yang kita butuhkan yang dalam hal ini adalah ngOnInit. Kata kunci super mengacu pada instance komponen yang sedang diwarisi dari mana dalam hal ini akan menjadi ComponentA.
sumber
jika Anda membaca perpustakaan CDK dan perpustakaan material, mereka menggunakan warisan tetapi tidak terlalu banyak untuk komponen itu sendiri, proyeksi konten adalah raja IMO. lihat tautan ini https://blog.angular-university.io/angular-ng-content/ di mana dikatakan "masalah utama dengan desain ini"
Saya tahu ini tidak menjawab pertanyaan Anda tetapi saya benar-benar berpikir mewarisi / memperluas komponen harus dihindari . Inilah alasan saya:
Jika kelas abstrak yang diperluas oleh dua atau lebih komponen berisi logika bersama: gunakan layanan atau bahkan buat kelas skrip baru yang dapat dibagi antara dua komponen.
Jika kelas abstrak ... berisi variabel yang dibagi atau fungsi onClicketc, Maka akan ada duplikasi antara html dari dua tampilan komponen yang diperluas. Ini adalah praktik buruk & html yang dibagikan harus dipecah menjadi Komponen. Komponen-komponen ini dapat dibagi antara dua komponen.
Apakah saya kehilangan alasan lain untuk memiliki kelas abstrak untuk komponen?
Contoh yang saya lihat baru-baru ini adalah komponen yang memperpanjang AutoUnsubscribe:
ini bas karena seluruh basis kode yang besar,
infiniteSubscriptions.push()
hanya digunakan 10 kali. Juga mengimpor & memperpanjangAutoUnsubscribe
benar-benar membutuhkan lebih dari sekedar kode menambahkanmySubscription.unsubscribe()
dalamngOnDestroy()
metode komponen itu sendiri, yang diperlukan logika tambahan pula.sumber
Jika ada yang mencari solusi yang diperbarui, jawaban Fernando cukup sempurna. Kecuali itu
ComponentMetadata
sudah usang. MenggunakannyaComponent
malah bekerja untuk saya.CustomDecorator.ts
File Dekorator Kustom lengkap terlihat seperti ini:Kemudian impor ke
sub-component.component.ts
file komponen baru Anda dan gunakan@CustomComponent
alih-alih@Component
seperti ini:sumber
Anda dapat mewarisi @Input, @Output, @ViewChild, dll. Lihatlah contoh:
sumber
Komponen dapat diperluas sama dengan warisan kelas naskah, hanya saja Anda harus menimpa pemilih dengan nama baru. Semua Properti Input () dan Output () dari Komponen Induk berfungsi seperti biasa
Memperbarui
@Component adalah dekorator,
Dekorator diterapkan selama deklarasi kelas bukan pada objek.
Pada dasarnya, dekorator menambahkan beberapa metadata ke objek kelas dan itu tidak dapat diakses melalui pewarisan.
Jika Anda ingin mencapai Warisan Dekorator, saya sarankan menulis dekorator khusus. Contohnya seperti di bawah ini.
Lihat: https://medium.com/@ttemplier/angular2-decorators-and-class-inheritance-905921dbd1b7
sumber
sumber