详解Angular 4.x 动态创建组件(2)

在上面代码中,我们调用容器的 createComponent() 方法,该方法内部将调用 ComponentFactory 实例的 create() 方法创建对应的组件,并将组件添加到我们的容器。

现在我们已经能获取新组件的引用,即可以我们可以设置组件的输入类型:

this.componentRef.instance.type = type;

同样我们也可以订阅组件的输出属性,具体如下:

this.componentRef.instance.output.subscribe(event => console.log(event));

另外不能忘记销毁组件:

ngOnDestroy() { this.componentRef.destroy(); }

最后我们需要将动态组件添加到 NgModule 的 entryComponents 属性中:

@NgModule({ ..., declarations: [AppComponent, AlertComponent], bootstrap: [AppComponent], entryComponents: [AlertComponent], }) export class AppModule { }

完整示例

exe-alert.component.ts

import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: "exe-alert", template: ` <h1 (click)="output.next(type)">Alert {{type}}</h1> `, }) export class AlertComponent { @Input() type: string = "success"; @Output() output = new EventEmitter(); }

app.component.ts

import { Component, ViewChild, ViewContainerRef, ComponentFactory, ComponentRef, ComponentFactoryResolver, OnDestroy } from '@angular/core'; import { AlertComponent } from './exe-alert.component'; @Component({ selector: 'exe-app', template: ` <ng-template #alertContainer></ng-template> <button (click)="createComponent('success')">Create success alert</button> <button (click)="createComponent('danger')">Create danger alert</button> ` }) export class AppComponent implements OnDestroy { componentRef: ComponentRef<AlertComponent>; @ViewChild("alertContainer", { read: ViewContainerRef }) container: ViewContainerRef; constructor(private resolver: ComponentFactoryResolver) { } createComponent(type: string) { this.container.clear(); const factory: ComponentFactory<AlertComponent> = this.resolver.resolveComponentFactory(AlertComponent); this.componentRef = this.container.createComponent(factory); this.componentRef.instance.type = type; this.componentRef.instance.output.subscribe((msg: string) => console.log(msg)); } ngOnDestroy() { this.componentRef.destroy() } }

app.module.ts

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { AlertComponent } from './exe-alert.component'; @NgModule({ imports: [BrowserModule], declarations: [AppComponent, AlertComponent], bootstrap: [AppComponent], entryComponents: [AlertComponent], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class AppModule { }

总结

获取装载动态组件的容器

在组件类的构造函数中,注入 ComponentFactoryResolver 对象

调用 ComponentFactoryResolver 对象的 resolveComponentFactory() 方法创建 ComponentFactory 对象

调用组件容器对象的 createComponent() 方法创建组件并自动添加动态组件到组件容器中

基于返回的 ComponentRef 组件实例,配置组件相关属性 (可选)

在模块 Metadata 对象的 entryComponents 属性中添加动态组件

declarations - 用于指定属于该模块的指令和管道列表

entryComponents - 用于指定在模块定义时,需要编译的组件列表。对于列表中声明的每个组件,Angular 将会创建对应的一个 ComponentFactory 对象,并将其存储在 ComponentFactoryResolver 对象中

我有话说

<ng-template> 与 <ng-container> 有什么区别?

通常情况下,当我们使用结构指令时,我们需要添加额外的标签来封装内容,如使用 *ngIf 指令:

<section *ngIf="show"> <div> <h2>Div one</h2> </div> <div> <h2>Div two</h2> </div> </section>

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wypgfz.html