基于配置动态引导加载Angular 5组件的技术问询
解决Angular 5动态加载指定仪表盘组件的方案
我之前在Angular 5项目里做过几乎一模一样的动态仪表盘需求,刚好能给你一套可行的实现步骤:
第一步:把获取到的组件列表存到全局服务
你已经用APP_INITIALIZER拿到了需要加载的组件列表,现在要做的是把这个列表存到一个可注入的服务里,方便后续模块和组件调用:
import { Injectable } from '@angular/core'; @Injectable() export class DashboardConfigService { requiredComponents: any[] = []; // 用来存从服务获取的组件列表 setComponents(components: any[]) { this.requiredComponents = components; } }
然后在APP_INITIALIZER里调用服务获取列表后,调用这个set方法:
export function loadDashboardConfig(configService: DashboardConfigService, apiService: ApiService) { return () => apiService.getRequiredComponents().subscribe(components => { configService.setComponents(components); }); } // 在AppModule的providers里配置 providers: [ DashboardConfigService, ApiService, { provide: APP_INITIALIZER, useFactory: loadDashboardConfig, deps: [DashboardConfigService, ApiService], multi: true } ]
第二步:动态创建模块并编译组件
因为Angular 5里动态加载组件必须让组件属于某个模块,并且在entryComponents里声明,所以我们需要根据拿到的组件列表动态生成一个模块,然后编译它:
先创建一个动态组件加载服务:
import { Injectable, Compiler, NgModule } from '@angular/core'; import { DashboardConfigService } from './dashboard-config.service'; @Injectable() export class DynamicComponentLoaderService { constructor(private compiler: Compiler, private configService: DashboardConfigService) {} async getComponentFactories() { // 动态创建模块,把需要的组件都加进去 @NgModule({ declarations: this.configService.requiredComponents, entryComponents: this.configService.requiredComponents // Angular 5必须配置这个 }) class DynamicDashboardModule {} // 编译模块,获取组件工厂 const moduleFactory = await this.compiler.compileModuleAndAllComponentsAsync(DynamicDashboardModule); // 返回所有组件的工厂 return moduleFactory.componentFactories; } }
第三步:在仪表盘容器里加载组件
接下来,在你的仪表盘容器组件里,通过ViewContainerRef来动态加载这些组件:
import { Component, ViewChild, ViewContainerRef, OnInit } from '@angular/core'; import { DynamicComponentLoaderService } from './dynamic-component-loader.service'; @Component({ selector: 'app-dashboard-container', template: `<div #componentContainer></div>` }) export class DashboardContainerComponent implements OnInit { @ViewChild('componentContainer', { read: ViewContainerRef }) container: ViewContainerRef; constructor(private loaderService: DynamicComponentLoaderService) {} async ngOnInit() { const componentFactories = await this.loaderService.getComponentFactories(); // 遍历每个组件工厂,创建并加载组件 componentFactories.forEach(factory => { const componentRef = this.container.createComponent(factory); // 如果需要给组件传数据,可以在这里处理 // componentRef.instance.data = yourData; }); } }
关键注意事项
- 确保你的每个仪表盘组件都是独立的,若组件有依赖其他模块,需要把依赖模块也加到动态模块的
imports数组里 - Angular 5中
compileModuleAndAllComponentsAsync是异步操作,必须用async/await或Promise处理结果 - 如果需要和动态加载的组件交互(传值/监听事件),可以通过
componentRef.instance直接访问组件实例
这样一来,应用启动时只会先执行APP_INITIALIZER里的服务请求,拿到需要的组件列表后才会编译并加载这些组件,不会提前加载所有组件啦!
内容的提问来源于stack exchange,提问作者Rakesh Bk
相关产品推荐
相关产品推荐

