Angular8中NgModuleFactoryLoader.load传入Function类型loadChildren报错如何解决
问题原因
Angular 8 开始官方弃用了字符串格式的loadChildren配置,改为动态导入的函数写法。你用到的NgModuleFactoryLoader.load()是专为旧版字符串路径设计的API,仅接收字符串类型参数,因此传入Function会抛出类型不匹配错误,且该API从Angular 8开始已标记为弃用,后续版本会逐步移除。
修复步骤
1. 调整接口类型定义
不要用宽泛的Function定义loadChildren,直接使用Angular官方提供的LoadChildren类型,保证类型准确性:
import { LoadChildren } from '@angular/router'; export interface DynamicComponentManifest { componentId: string; path: string; loadChildren: LoadChildren; }
2. 替换加载逻辑
无需再使用NgModuleFactoryLoader,直接执行loadChildren函数即可获取目标模块,同时注入Compiler处理模块编译逻辑:
首先在服务的构造函数中注入Compiler,替换掉原来的NgModuleFactoryLoader注入:
import { Compiler } from '@angular/core'; constructor( private injector: Injector, private compiler: Compiler // 新增注入Compiler // 移除原来的NgModuleFactoryLoader注入 ) {}
然后修改getComponentFactory的加载逻辑:
import { from, of, throwError, mergeMap } from 'rxjs'; import { NgModuleFactory, Type, ComponentFactory, Injector } from '@angular/core'; public getComponentFactory<T>( componentId: string, injector?: Injector, ): Observable<ComponentFactory<T>> { const manifest = this.manifests.find(m => m.componentId === componentId); if (!manifest) { return throwError(`DynamicComponentLoader: Unknown componentId "${componentId}"`); } // 直接执行loadChildren函数,将返回的Promise转为Observable return from(Promise.resolve(manifest.loadChildren())).pipe( mergeMap(moduleOrFactory => { let ngModuleFactory: NgModuleFactory<any>; // 兼容两种返回格式:ViewEngine下返回NgModuleFactory,Ivy下返回模块类 if (moduleOrFactory instanceof NgModuleFactory) { ngModuleFactory = moduleOrFactory; } else { ngModuleFactory = this.compiler.compileModuleSync(moduleOrFactory as Type<any>); } const moduleRef = ngModuleFactory.create(injector || this.injector); const dynamicComponentType = moduleRef.injector.get(DYNAMIC_COMPONENT, null); if (!dynamicComponentType) { throw new Error( `DynamicComponentLoader: Dynamic module for componentId "${componentId}" does not contain DYNAMIC_COMPONENT as a provider.` ); } return of(moduleRef.componentFactoryResolver.resolveComponentFactory<T>(dynamicComponentType)); }) ); }
3. 保证loadChildren配置符合规范
你的manifest配置中loadChildren需要按照Angular 8+的动态导入写法:
const manifests: DynamicComponentManifest[] = [ { componentId: 'your-component-id', path: 'your-path', loadChildren: () => import('./path/to/your.module').then(m => m.YourCustomModule) } ];
内容的提问来源于stack exchange,提问作者ShivamPatel
相关产品推荐
相关产品推荐

