主要用到的APIs有:
-
ViewChild
: 装饰器,对组件视图内的元素进行查询,可以理解为jquery的选择器 -
ComponentRef
:抽象类,组件引用,提供访问组件实例的接口和组件实例相关的其它对象,以及销毁组件实例的方法 -
ComponentFactory
: 抽象类, 组件工厂,可以理解为创建组件的recipe, 内部有一个create()
方法来创建组件 -
ComponentFactoryResolver
: 抽象类,可当作服务注入, 这个有个resolveComponentFactory()
返回一个ComponentFactory
-
ViewContainerRef
: 表示视图组件容器的引用 -
entryComponents
: 这个用于声明动态注入的组件
示例
动态的创建一个AlertComponent
组件
AlertComponnet:
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-selector',
template: `
<h1> alert {{ info }}</h1>
`
})
export class AlertComponent {
@Input() info: string = 'information'; // 输入属性
}
AppComponent
import {
Component,
ComponentRef,
ComponentFactory,
ComponentFactoryResolver,
ViewChild,
ViewContainerRef,
OnDestroy
} from '@angular/core';
import { AlertComponent } from './alert.component';
@Component({
selector: 'app-root',
template: `
<div>
<ng-template #alertContainer></ng-template> // 这里放动态生产的AlertComponent组件
<button (click)="createAlert('success')">创建成功alert组件</button>
<button (click)="createAlert('warning')">创建警告alert组件</button>
</div>
`
})
export class AppComponent implements OnDestroy {
// 查找到 <ng-template> 元素
// { read: ViewContainerRef }) 表示将这个元素(<ng-template>)当作视图容器的引用
@ViewChild('alertContainer', { read: ViewContainerRef }) container: ViewContainerRef;
componentRef: ComponentRef<AlertComponent>; // 表示对AlertComponent组件的引用
constructor(
// ComponentFactoryResolver 暴露一个重要的方法 'resolveComponentFactory'
// 'resolveComponentFactory()' 接收一个组件当作参数, 返回一个 ComponentFactory
private resolver: ComponentFactoryResolver // 注入这个服务
){}
createAlert(msg) {
this.container.clear(); // 表示一上来先清空视图容器
// 创建组件工厂
const factory: ComponentFactory<AlertComponent> = this.resolver.resolveComponentFactory(AlertComponent);
// 动态的创建该组件
// createComponent() 内部其实是调用factory内部的create()方法
this.componentRef = this.container.createComponent(factory);
// this.componentRef.instance 表示 组件实例
this.componentRef.instance.info = msg;
}
ngOnDestroy(): void {
this.componentRef.destroy(); // 最后别忘记了销毁该组件
}
}
上面的过程详解:
// 这个表示将容器清空
// 如果不清空的话,创建的组件将不停的添加到视图容器中(如果这是你想要的效果,可以不必调用这个方法)
this.container.clear();
最后将动态插入的组件添加到 entryComponents
中:
import { AppComponent } from './app.component';
import { AlertComponent } from './components/alert/alert.component';
@NgModule({
declarations: [
AppComponent,
AlertComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
entryComponents: [AlertComponent], // 动态创建的组件
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
}
最后效果如图:
参考文章: