如何动态的插入一个组件

主要用到的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 {
}

最后效果如图:


动态创建组件.png

参考文章:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容