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();
}
}
父组件模板:
扫描二维码关注公众号,回复:
14459388 查看本文章

<app-ad-banner [ads]="ads"></app-ad-banner>
最终显示效果是这样的: