angular - 动态加载组件

363 阅读1分钟

来自angular官网个人学习笔记

🌰 轮播图的动态加载案例

添加指令

编写组件之前,自定义一个指令AdDirective告诉angular这个组件的插入位置

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[adHost]',
})
export class AdDirective {
  constructor(public viewContainerRef: ViewContainerRef) { }
}

ViewContainerRef用于获取需要动态添加component的视图容器
@Directive 指令使选择器修饰adHost,用于申请指令到element中。

指令使用到组件上

 <ng-template> 可以很好的使用刚才定义的指令生成动态组件,因为它没有渲染出任何额外的组件.
为了发出一个AdDirective, 我们从 ad.directive.ts中调用[adHost]指令, 去掉方括号就可以在 <ng-template>中使用。

//ad-banner.component.ts
template: `
  <div class="ad-banner-example">
    <h3>Advertisements</h3>
    <ng-template adHost></ng-template>
  </div>
`

动态加载的具体实现

所注入的参数AdItem将最终来自请求的轮播数据。让我们的AdBannerComponent能够被动态渲染。
getAds()方法每三秒调用一次loadComponent()。来每次加载一些AdItems数组的新组件。

//ad-banner.component.ts
export class AdBannerComponent implements OnInit, OnDestroy {
  @Input() ads: AdItem[] = [];

  currentAdIndex = -1;

  @ViewChild(AdDirective, {static: true}) adHost!: AdDirective;
  interval: number|undefined;

  ngOnInit(): void {
    this.loadComponent();
    this.getAds();
  }

  ngOnDestroy() {
    clearInterval(this.interval);
  }

  loadComponent() {
  //将 currentAdIndex 设为目前的值+1,除以AdItem的长度来赋给 currentAdIndex
  //之后再使用这个值去从数组里选择一个adItem
    this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length;
    const adItem = this.ads[this.currentAdIndex];
    
//`AdDirective`注入`ViewContainerRef`到它的构造函数中。这就是指令访问您要用于托管动态组件的元素的方式。
//要将组件添加到模板中,请调用ViewContainerRef.createComponent
    const viewContainerRef = this.adHost.viewContainerRef;
    viewContainerRef.clear();

    const componentRef = viewContainerRef.createComponent<AdComponent>(adItem.component);
    componentRef.instance.data = adItem.data;
  }

  getAds() {
    this.interval = setInterval(() => {
      this.loadComponent();
    }, 3000);
  }
}

效果

image.png