乐趣区

关于前端:angular动态组件加载器的个人理解

本文是基于 angular 官网文档所给出的代码来进行的。
传送门
咱们以广告为例来展现其相应性能。
上面是咱们想要实现的成果:

咱们会发现广告有不同大小,格局。同一个格局下会有不同的内容。上面咱们先来阐明这是如何实现的。
广告的每一种格局都对应着一个组件,而这些组件都要实现一个独特的接口用来把数据传给组件。

咱们实例中的接口很简略,只申明了 data 项,在应用中咱们还能够进行更加细化的设置:

// 广告组件实现的公共接口
export interface AdComponent {data: any;}

之后咱们便能够像上面这样编写咱们的广告栏的款式:

@Component({
  template: `
    <div class="job-ad">
      <h4>{{data.headline}}</h4>
      {{data.body}}
    </div>
  `
})
export class HeroJobAdComponent implements AdComponent {
  // 承受传入的 data
  @Input() data: any;}

之后咱们还须要像上面这样对整个广告的内容进行规定——申明格局起源组件和广告内容

export class AdItem {constructor(public component: Type<any>, public data: any) {}}

之后咱们就能够转接到服务层编写广告的获取操作:

@Injectable()
export class AdService {getAds() {
    return [
      new AdItem(
        HeroProfileComponent,
        {name: 'Bombasto', bio: 'Brave as they come'}
      ),
      new AdItem(
        HeroProfileComponent,
        {name: 'Dr IQ', bio: 'Smart as they come'}
      ),
        . . .
    ];
  }
}

之后便到了最重要的局部——动静组件加载器。

在增加组件之前,先要定义一个锚点来通知 Angular 要把组件插入到什么中央。
应用一个名叫 AdDirective 的辅助指令来在模板中标记出无效的插入点。

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

AdDirective 注入了 ViewContainerRef 来获取对容器视图的拜访权,这个容器就是那些动静退出的组件的宿主。
此处集体了解为:ViewContainerRef 就能够实现在以后组件中插入显示其余组件内容的性能。

咱们先把动静组件加载器中残缺代码放进去:

export class AdBannerComponent implements OnInit, OnDestroy {@Input() ads: AdItem[] = [];

  currentAdIndex = -1;

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

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

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

  loadComponent() {
    // 以后的广告,用于在 Ads 数组中循环取样
    this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length;
    const adItem = this.ads[this.currentAdIndex];

    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);
  }
}

首先咱们通过 @ViewChild 注解用于从模板视图中获取匹配的元素也就是获取咱们下面配置的锚点。
接下来,咱们要把 viewContainerRef 指向这个组件的现有实例。

这里的 loadComponent() 办法很重要。它先选取了一个广告。

要把这个组件增加到模板中,咱们能够调用 ViewContainerRef 的 createComponent()。
createComponent() 办法返回一个援用,指向这个刚刚加载的组件。应用这个援用就能够与该组件进行交互,比方设置它的属性或调用它的办法。

也就是说咱们须要把要显示的广告的组件通过 viewContainerRef 与 componentRef 进行绑定,而后再把广告的 data 传给 componentRef.instance,而这个 componentRef 便是咱们所要展现的。

之后咱们要做的就是每隔肯定工夫循环调用 loadComponent(),在此处咱们应用如下代码实现:

 interval: number|undefined;

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

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

到此咱们的动静组件加载器便已实现,咱们应用时只需在想要显示广告的页面中进行这样调用即可:

// V 层
<div>
      <app-ad-banner [ads]="ads"></app-ad-banner>
</div>

其中的 ads 是通过下面的 M 层获取的。

   // c 层
   this.ads = this.adService.getAds();
退出移动版