Angular之动态加载组件

Angular组件的模板不会永远是固定的,在实际应用程序中,可能需要在运行期间动态加载组件。
参照Angular官方示例,练习一下Angular的动态加载组件。

1.确定组件加载位置

自定义一个指令,用于确定组件显示的锚点位置。

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

@Directive({
    
    
  selector: '[adHost]'
})
export class AdDirective {
    
    

  constructor(public viewContainerRef : ViewContainerRef) {
    
     }

}

2.定义组件

2.1标准化接口

定义一个标准化API接口组件,用于数据传递。

export interface AdComponent {
    
    
    data : any;
}

2.2实现类

定义它的实现类,用于在界面动态加载展示。
HeroJobAdComponent:

import {
    
     Component, OnInit, Input } from '@angular/core';
import {
    
     AdComponent } from './adcomponent';

@Component({
    
    
  template: `
    <div class="job-ad">
      <h4>{
     
     {data.headline}}</h4>
      {
     
     {data.body}}
    </div>
  `,
  styles: [
    '.job-ad {border: 1px solid gray; padding: 5px; padding-bottom: 20px; padding-left: 20px; border-radius: 10px; background-color: lightblue; color: black;}'
  ]
})
export class HeroJobAdComponent implements OnInit, AdComponent {
    
    
  @Input() data : any;

  constructor() {
    
     }

  ngOnInit(): void {
    
    
  }

}

HeroProfileComponent:

import {
    
     Component, OnInit, Input } from '@angular/core';
import {
    
     AdComponent } from './adcomponent';

@Component({
    
    
  template: `
    <div class="hero-profile">
      <h3>Featured Hero Profile</h3>
      <h4>{
     
     {data.name}}</h4>
      <p>{
     
     {data.bio}}</p>
      <strong>Hire this hero today!</strong>
    </div>
  `,
  styles: [
    '.hero-profile {border: 1px solid gray; padding: 5px; padding-bottom: 20px; padding-left: 20px;border-radius: 10px;background-color: lightgreen;color: black;}'
  ]
})
export class HeroProfileComponent implements OnInit, AdComponent {
    
    

  @Input() data: any;

  constructor() {
    
     }

  ngOnInit(): void {
    
    
  }

}

2.3定义数据模型

创建一个数据模型类,用于定义数据结构。

import {
    
     Type } from '@angular/core';

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

2.4定义服务

创建一个服务,用于模拟获取数据。

import {
    
     Injectable } from '@angular/core';
import {
    
     AdItem } from './aditem';
import {
    
     HeroProfileComponent } from './heroprofile.component';
import {
    
     HeroJobAdComponent } from './herojobad.component';

@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' }
      ),
      new AdItem(
        HeroJobAdComponent,
        {
    
     headline: 'Hiring for several positions', body: 'Submit your resume today!' }
      ),
      new AdItem(
        HeroJobAdComponent,
        {
    
     headline: 'Openings in all departments', body: 'Apply today' }
      )
    ];
  }
}

2.5定义主组件

创建主组件类,用于界面渲染。

import {
    
     Component, OnInit, OnDestroy, ComponentFactoryResolver, ViewChild, Input } from '@angular/core';
import {
    
     AdDirective } from './ad.directive';
import {
    
     AdItem } from './aditem';
import {
    
     AdComponent } from './adcomponent';

@Component({
    
    
  selector: 'app-ad-banner',
  template: `
    <div class="ad-banner-example">
      <h3>Advertisements</h3>
      <ng-template adHost></ng-template>
    </div>
  `,
  styles: [
    '.ad-banner-example {width: 400px;}',
  ]
})
export class AdBannerComponent implements OnInit, OnDestroy {
    
    
  @Input() ads : AdItem[] = [];
  currentAdIndex = -1;
  interval: any | undefined;

  @ViewChild(AdDirective, {
    
    static : true}) adHost !: AdDirective

  constructor(private componentFactoryResolver : ComponentFactoryResolver) {
    
     }
  
  ngOnInit(): void {
    
    
    this.loadComponent();
    this.getAds();
  }

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

  loadComponent() {
    
    
    this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length;
    const currentAdItem = this.ads[this.currentAdIndex];
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(currentAdItem.component);
    const viewContainerRef = this.adHost.viewContainerRef;
    viewContainerRef.clear();
    const componentRef = viewContainerRef.createComponent<AdComponent>(componentFactory);
    componentRef.instance.data = currentAdItem.data;
  }

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

3.引入并加载组件

在父界面引入并加载组件:

import {
    
     NgModule } from '@angular/core';

import {
    
     PersonComponent } from '../person/person.component';
import {
    
     MenuComponent } from './menu/menu.component';
import {
    
     ContentComponent } from './content/content.component';
import {
    
     FormsModule } from '@angular/forms';
import {
    
     ChangehooktestComponent } from '../changehooktest/changehooktest.component';
import {
    
     BrowserModule } from '@angular/platform-browser';

import {
    
     AdBannerComponent } from '../dynamiccomponentstest/ad-banner.component';
import {
    
     HeroProfileComponent } from '../dynamiccomponentstest/heroprofile.component';
import {
    
     HeroJobAdComponent } from '../dynamiccomponentstest/herojobad.component';
import {
    
     AdService } from '../dynamiccomponentstest/ad.service';
import {
    
     AdDirective } from '../dynamiccomponentstest/ad.directive';

@NgModule({
    
    
  providers: [
    AdService
  ],
  declarations: [
    AdBannerComponent,
    HeroProfileComponent,
    HeroJobAdComponent,
    AdDirective,
  ],
  imports: [
    FormsModule,
    BrowserModule,
  ],
  exports: [
  ],
})
export class CommonModule {
    
     }

父组件:

import {
    
     Component, OnInit, ViewEncapsulation, ViewChild } from '@angular/core';
import {
    
     CommonService } from '../common.service';
import {
    
     AdItem } from '../../dynamiccomponentstest/aditem';
import {
    
     AdService } from '../../dynamiccomponentstest/ad.service';

@Component({
    
    
  selector: 'app-content',
  templateUrl: './content.component.html',
  styleUrls: ['./content.component.css'],
  encapsulation: ViewEncapsulation.None,
  providers: [CommonService],
})
export class ContentComponent implements OnInit {
    
    
  ads : AdItem[] = [];
  constructor(private adService : AdService) {
    
    }
  ngOnInit(): void {
    
    
    this.ads = this.adService.getAds();
  }
}

父组件模板:

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

最终显示效果是这样的:
在这里插入图片描述

4.附上程序源码

【点击下载】

猜你喜欢

转载自blog.csdn.net/verkand1/article/details/121413341
今日推荐