Angular组件--动态组件

动态创建组件的应用场景很多,比如动态广告、像浏览器一样动态打开多个页面等等等等

要动态创建组件主要需要用到angular中的ComponentFactoryResolverComponentFactoryViewContainerRef ComponentRef这几个类

class ComponentFactoryResolver {
  static NULL: ComponentFactoryResolver
  resolveComponentFactory<T>(component: Type<T>): ComponentFactory<T>
}
class ViewContainerRef {
  get element(): ElementRef
  get injector(): Injector
  get parentInjector(): Injector
  clear(): void
  get(index: number): ViewRef|null
  get length(): number
  createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number): EmbeddedViewRef<C>
  createComponent<C>(componentFactory: ComponentFactory<C>, index?: number, injector?: Injector, projectableNodes?: any[][], ngModule?: NgModuleRef<any>): ComponentRef<C>
  insert(viewRef: ViewRef, index?: number): ViewRef
  move(viewRef: ViewRef, currentIndex: number): ViewRef
  indexOf(viewRef: ViewRef): number
  remove(index?: number): void
  detach(index?: number): ViewRef|null
}
class ComponentRef<C> {
  get location(): ElementRef
  get injector(): Injector
  get instance(): C
  get hostView(): ViewRef
  get changeDetectorRef(): ChangeDetectorRef
  get componentType(): Type<any>
  destroy(): void
  onDestroy(callback: Function): void
}

假设我们要在组件A中动态创建组件B,那么我们一般会这样做:

1、在组件A中设置一个<ng-template>,并在组件类中获取它。

2、在组件A中导入组件B,导入上面说的那几个类

3、在组件A中动态创建组件B的方法里使用ComponentFactoryResolver的resolveComponentFactory方法解析组件B获得组件B的ComponentFactory,balabalabala...具体如下

4、在所在模块中导入entryComponents: [BComponent]

@NgModule({
  ...
  declarations: [...,BComponent],
  entryComponents: [BComponent]
})
import { Component, OnInit, ViewChild, ComponentRef, ComponentFactory,
  ComponentFactoryResolver, ViewContainerRef } from '@angular/core';

import { BComponent } from '../b/b.component';

@Component({
  selector: 'app-article',
  template: `<ng-template #RefB></ng-template><button (click)="createComponent()">create</button> `
})
export class ArticleComponent implements OnInit {

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

  constructor(
    private componentFactoryResolver: ComponentFactoryResolver) { }

  ngOnInit() {}

  createComponent() {
    const componentFactory: ComponentFactory<BComponent> = this.componentFactoryResolver.resolveComponentFactory(BComponent);
    const componentRef: ComponentRef<BComponent> = this.container.createComponent(componentFactory);
  }

}

至此我们完成了对组件B的基本动态创建方法,我们还可以通过componentRef的instance方法来访问组件B中的属性和方法;

但是当我们不仅仅是希望能动态创建,同时还想要能让动态创建出的组件B能和组件A进行通讯,就需要使用@Input、@Output。这与平时我们所使用的过程有一点区别,因为动态创建出的组件无法绑定属性,则需要在父组件A通过订阅才能实现通讯。

//input
componentRef.instance.type = type;
//output
componentRef.instance.output.subscribe(event => console.log(event));

以前做过一个很复杂的的动态创建的组件交互中的Input需要使用Subject订阅才能实现的,记不清楚了具体是什么场景了,用来作甚么的了

转载于:https://my.oschina.net/u/3412211/blog/1550642

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值