angular中动态创建组件(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zgrbsbf/article/details/81585567

最近做东西用到了大量动态组件相关的知识,先总结一下一种比较简单的。

已经有了一个组件,AppComponent,也有一个将要动态创建的组件MsgComponent,

@Component({
  selector: 'msg',
  template: `
      <h3>{{type}}</h3>
  `
})
export class MsgComponent {
  type = '123';
}

那么就得有个地方“放”这个动态创建出来的组件,这个地方就叫做容器(container),AppComponent中的容器是这样子的:

template: `
    <h1 #msgContainer>我是Container</h1>
  `,

然后在AppComponent中拿到这个容器:

  @ViewChild('msgContainer', {read: ViewContainerRef}) container;

ViewChild挺强大的;参数设置成ViewContainerRef用来控制container这个变量的类型,视图容器类型。
ViewContainerRef的文档在这里

https://angular.io/api/core/ViewContainerRef

abstract class ViewContainerRef {
  ...
  abstract createComponent<C>(componentFactory: ComponentFactory<C>, index?: number, injector?: Injector, projectableNodes?: any[][], ngModule?: NgModuleRef<any>): ComponentRef<C>
  ...
}

如此一来,container这个实例上就可使用createComponent方法来创建组件了。这个方法的参数比较多,但是只有第一个参数是必须的,别的我也没用过。

第一个参数是一个ComponentFactory的实例,

打一个比喻:container好比是一个小程序员,他有写代码的能力,这个能力叫做createComponent,但是他不知道具体怎么写,他得看需求文档,这个文档就是一个ComponentFactory实例。如何得到这个实例?

组件工厂解析器:ComponentFactoryResolver
组件工厂解析器可以产生一个组件工厂(ComponentFactory),在AppComponent中通过依赖注入获得一个组件工厂解析器:

constructor(private resolver: ComponentFactoryResolver) {
  }

然后就可以创建一个组件工厂,之后交给容器根据这个工厂来创建组件:

const factory: ComponentFactory<MsgComponent> = this.resolver.resolveComponentFactory(MsgComponent);
this.componentRef = this.container.createComponent(factory);

AppComponent的代码如下:

@Component({
  selector: 'my-app',
  template: `
    <h1 #msgContainer>我是Container</h1>
    <button (click)="createComponent()">来一个</button>
  `,
  entryComponents: [MsgComponent], // 或者加到模块中也可以
})
export class AppComponent {
  @ViewChild('msgContainer', {read: ViewContainerRef}) container;
  componentRef: ComponentRef<MsgComponent>;

  constructor(private resolver: ComponentFactoryResolver) {
  }

  createComponent() {
    const factory: ComponentFactory<MsgComponent> = this.resolver.resolveComponentFactory(MsgComponent);

    this.componentRef = this.container.createComponent(factory); // Internally this method will call the create() method from the factory and will append the component as a sibling to our container.

    console.log('componentRef',this.componentRef);

    this.componentRef.instance.type = Math.random() + '';
  }
}

通过componentRef就可以拿到新建的组件实例了:
这里写图片描述

这里写图片描述
从上图中可以看到,新的组件被追加到了容器中,如果希望清空容器,可以创建组件之前调用:

   this.container.clear();

参考文献:
https://netbasal.com/dynamically-creating-components-with-angular-a7346f4a982d

猜你喜欢

转载自blog.csdn.net/zgrbsbf/article/details/81585567