-----------------------------2022年0409更新------------------------
源码下载:angular8实现动态加载组件-Javascript文档类资源-CSDN下载
同时官方最新文档里面,有一篇也说到了动态加载组件
-----------------------------------原文----------------------------------------
业务场景: 动态数据源的tab切换框(tab的个数、名称、里面的内容是 动态的)。
场景说明: ① 用户通过前台交互, 增加/删除某一类型的tab标签页,
② 将tab标签页的变化存储到后台
③ 从后台拿到新的tab标签页数据以后,渲染为 tab切换框。(这里只讨论③的实现)
注意:
① 实现动态加载组件,最重要的3个部分:viewchild,viewContainerRef , componentFactoryResolver
② angular8 中viewchild 需要2个参数,一个是模板变量的名称,另一个一般默认是{ static:false }
代码部分:
目录结构(因为是个demo,所以结构比较简单,dynamic-tab-set组件就是动态加载组件的 tab切换框组件。dy1和dy2组件没什么东西,就是2个简单的初始化组件)
dynamic-tab-set.component.ts (为了方便演示,数据源就是假设的数据源 。dy1/2 既是需要加载的组件名,又是tab按键名,即tab的个数,名称,加载的内容是动态的,由后台数据源控制。)
//ViewChild 属性装饰器, 通过组件的模板变量,来获取组件元素。(可用作父子间组件通信的方式)
//ViewContainerRef 视图容器,在里面可以增,删组件
//ComponentFactoryResolver 动态加载组件的服务
import { Component, OnInit, ViewContainerRef, ViewChild, ComponentFactoryResolver } from '@angular/core';
import { dynamicComponent } from '../dynamiModule';
@Component({
selector: 'app-dynamic-tab-set',
templateUrl: './dynamic-tab-set.component.html',
styleUrls: ['./dynamic-tab-set.component.scss']
})
export class DynamicTabSetComponent implements OnInit {
@ViewChild('componentContainer', { static: false, read: ViewContainerRef }) componentContainer: ViewContainerRef;
//假设这是从后台拿取的数据。
tabsData = [{
name: 'dy1'
}, {
name: 'dy2'
}]
constructor(private cfr: ComponentFactoryResolver) { }
ngOnInit() {
}
getDynamicComponents(name) {
this.componentContainer.clear();
let component = this.cfr.resolveComponentFactory(dynamicComponent[name]);
this.componentContainer.createComponent(component);
}
}
dynamic-tab-set.component.html
<ng-container *ngIf="tabsData && tabsData.length > 0">
<!-- tab键 -->
<ng-container *ngFor="let tabData of tabsData">
<button (click)="getDynamicComponents(tabData.name)">{{tabData.name}}</button>
</ng-container>
<!-- 组件容器 -->
<div #componentContainer></div>
</ng-container>
dynamiModule.ts (由于 动态的组件,① 需要在当前module下 declarations数组中声明,②需要在当前module下 entryComponents数组中声明 ③ 需要在tab切换框页面 导入。 所以需要多次多个地方重复写import,太麻烦了)(参考文章)
import { Dy1Component } from './dy1/dy1.component';
import { Dy2Component } from './dy2/dy2.component';
const dynamicComponent = {
'dy1': Dy1Component,
'dy2': Dy2Component
}
const importComponents = [Dy1Component, Dy2Component];
export { dynamicComponent, importComponents }
app.component.html
<app-dynamic-tab-set></app-dynamic-tab-set>
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { DynamicTabSetComponent } from './dynamic-tab-set/dynamic-tab-set.component';
import { importComponents } from './dynamiModule';
@NgModule({
declarations: [
AppComponent,
DynamicTabSetComponent,
[...importComponents]
],
entryComponents: [
[...importComponents],
],
imports: [
BrowserModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }