Sisipan paparan dinamik API asli telah diperkenalkan sebelum ini dan fungsi itu sudah boleh memenuhi kebanyakan senario penggunaan. Walau bagaimanapun, terdapat beberapa kelemahan Ia masih belum menyelesaikan keperluan untuk memasukkan kandungan di luar aplikasi Angular, dan arahan tidak boleh mempunyai interaksi input dan output dengan komponen yang dimasukkan secara dinamik.
Mujurlah, Angular menyediakan set kit pembangunan komponen Component Dev Kit (CDK) secara rasmi sebagai alat asas untuk pembangunan pelbagai komponen Sudut, termasuk "Portal" untuk membantu dalam penciptaan paparan dinamik .
"Paparan dinamik" ini boleh menjadi komponen, TemplateRef atau elemen DOM, sepadan dengan tiga jenis Portal (ComponentPortal, TemplatePortal, DomPortal). Kelas asas generik abstrak bagi ketiga-tiga daripadanya ialah Portal<T>
, yang mempunyai tiga kaedah: pasang (lekapkan pada bekas), tanggalkan (alih keluar daripada bekas) dan isAttached (tentukan sama ada paparan dipasang).
Bekas juga ditakrifkan oleh kelas abstrak BasePortalOutlet
, yang serupa dengan paparan dan termasuk lampirkan (lekapkan paparan pada bekas), tanggalkan (alih keluar pandangan dari bekas), buang (musnahkan bekas), isAttached (sama ada Terdapat pandangan yang dipasang). Pelaksanaan utamanya ialah kelas DomPortalOutlet
. Digunakan untuk melekapkan tiga jenis paparan dinamik.
Mari kita lihat dahulu penciptaan tiga paparan dinamik.
ComponentPortal
Berbanding dengan API asli, adalah sangat mudah untuk mencipta komponen dinamik anda hanya perlu memasukkan kelas komponen fungsi Just binaan ComponentPortal
.
this.componentPortal = new ComponentPortal(ExampleComponent);
Anda boleh lulus dalam mana-mana kelas komponen tersuai untuk mencipta objek ComponentPortal
dan kemudian memasukkannya secara dinamik ke dalam paparan.
✨Nota: Adalah disyorkan untuk menggunakan pengkompil Ivy untuk versi selepas Angular 9. Jika ia adalah versi lama pengkompil, kelas komponen yang diluluskan perlu diisytiharkan dalam entryComponents
Modul, dan Modul ini tidak boleh dimuatkan secara malas.
TemplatePortal
Berbanding dengan komponen, pembinaan TemplatePortal mempunyai satu lagi parameter (ViewContainerRef). Anda sepatutnya sudah biasa dengannya selepas membaca artikel sebelumnya Anda perlu bergantung padanya untuk menghubungi createEmbeddedView()
untuk membuat paparan terbenam. Di sini, melalui suntikan pembina, contoh ViewContainerRef
bagi komponen semasa digunakan secara langsung.
<ng-template #testTemplate> <p>一些需要动态插入的内容.</p> </ng-template>
@ViewChild('testTemplate') templatePortalContent: TemplateRef<any>; constructor(private _viewContainerRef: ViewContainerRef) { } ngAfterViewInit() { this.templatePortal = new TemplatePortal( this.templatePortalContent, this._viewContainerRef ); }
Selain pembina, TemplatePortal juga mempunyai arahan (CdkPortal) yang boleh dibuat dengan mudah.
<ng-template cdkPortal> <p>一些需要动态插入的内容.</p> </ng-template> <!-- 或写作 --> <!-- 和上面写法是一致的效果 --> <p *cdkPortal> 一些需要动态插入的内容. </p>
Kemudian melalui @ViewChild
anda boleh mendapatkan contoh TemplatePortal
.
DomPortal
Sama seperti contoh di atas, dapatkan contoh Templat melalui @ViewChild
untuk menciptanya. Begitu juga, anda juga boleh mendapatkannya ElementRef untuk mencipta DOM yang dinamik.
<div #domPortalContent><span>原生DOM内容</span></div>
@ViewChild('domPortalContent') domPortalContent: ElementRef<HTMLElement>; ngAfterViewInit() { this.domPortal = new DomPortal(this.domPortalContent); }
Anda boleh mengalihkan DOM ini ke mana-mana lokasi secara dinamik. Perlu diingat bahawa selepas pemindahan, arahan pengikatan atau pengikat data asal mungkin tidak lagi dikemas kini.
Tiga jenis Portal sebelumnya telah mengatakan bahawa ia boleh diberikan kepada mana-mana kedudukan, jadi bagaimana untuk memaparkannya secara khusus?
CdkPortOutlet
Cara paling mudah ialah dengan lulus arahan CdkPortOutlet:
<div> <ng-template [cdkPortalOutlet]="anyPortal"></ng-template> </div>
Lepasi nilai ke anyPortal
Mana-mana contoh Portal antara ketiga-tiganya akan dipaparkan secara dinamik kepada kedudukan semasa.
Berbeza daripada arahan API asli, ia secara automatik boleh menentukan jenis Portal itu. Selain itu, ia mempunyai acara tambahan: attached
Melalui acara ini, anda boleh mendapatkan contoh komponen yang dipasang atau TemplateRef. Ini juga menjadikan interaksi dengan komponen yang dipasang sangat mudah.
Bina contoh kontena
Tetapi memandangkan ia boleh diberikan ke mana-mana lokasi, ia secara semula jadi juga termasuk di luar aplikasi Angular , yang perlu diberikan kepada aplikasi Selain itu, kita perlu mencipta contoh bekas melalui pembina.
Kelas kontena ini ialah DomPortalOutlet
, yang merupakan subkelas pelaksanaan PortalOutlet
. Parameter pembinaannya adalah terutamanya: Elemen (nod DOM bagi paparan yang dipasang), ComponentFactoryResolver (sama seperti artikel sebelumnya, digunakan untuk membina komponen secara dinamik), appRef (contoh keseluruhan aplikasi Sudut semasa), Injector (penyuntik, digunakan untuk lulus tanggungan).
constructor( private viewContainerRef: ViewContainerRef, @Inject(DOCUMENT) private document: any, private injector: Injector, private componentFactoryResolver: ComponentFactoryResolver ) { // 在<body>下创建外部宿主元素 const container = this.document.createElement('div'); container.classList.add('outside-portal-container'); this.outsideContainer = this.document.body.appendChild(container); // 获取应用实例 this.appRef = this.injector.get(ApplicationRef); // 创建外部容器 this.outsideOutlet = new DomPortalOutlet( this.outsideContainer, this.componentFactoryResolver, this.appRef, this.injector ); } // 在应用外部插入动态组件。 openComponentPortalOutSideAngularContext(): void { const componentPortal = new ComponentPortal(AlertComponent); const componentRef = this.outsideOutlet.attach(componentPortal); componentRef.instance.closeAlert.subscribe(() => { this.outsideOutlet.detach(); }); } // 在应用外部插入动态模板。 openTemplatePortalInsideAngularContext(): void { const templatePortal = new TemplatePortal(this.templatePortalContent, this.viewContainerRef); this.outsideOutlet.attach(templatePortal); }
Selain memasang paparan ke dalam elemen DOM di luar aplikasi, anda juga perlu boleh berinteraksi dengan paparan Komponen boleh menyuntik kebergantungan dan templat boleh lulus dalam objek konteks.
const injectionToken = new InjectionToken<any>('Sharing data with outside component portal'); const customInjector = Injector.create({ providers: [{ provide: CustomInjectionToken, useValue: 'test value' }] });
Ubah suai sedikit kod untuk mencipta outsideContainer dan masukkan customInjector sebagai parameter (bukannya menggunakan penyuntik komponen semasa)
// 重点是第四个参数 new DomPortalOutlet(this.outsideContainer, this.componentFactoryResolver, this.appRef, customInjector);
Oleh itu, komponen ini hanya memerlukan Hanya tekan injectionToken ini untuk menyuntik kebergantungan:
constructor(@Inject(injectionToken) public customData: any) {}
Adalah mudah untuk menghantar konteks ke templat Apabila mencipta objek TemplatePortal, hanya masukkan objek konteks:
// 重点是第三个参数 new TemplatePortal(this.templatePortalContent, this.viewContainerRef, { customData:'test values' });
Keupayaan untuk berinteraksi dengan melihat data yang disisipkan ke luar;
Dengan itu, lebih mudah untuk mencipta bekas komponen dinamik, tetingkap timbul, menu terapung atau membina platform reka bentuk kod rendah.
Untuk lebih banyak pengetahuan berkaitan pengaturcaraan, sila layari:Pengenalan kepada Pengaturcaraan
! !
Atas ialah kandungan terperinci Ajar anda langkah demi langkah cara membuat kandungan dinamik menggunakan Portal CDK Sudut. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!