Angular两个组件互相引用执行--prod AOT编译报循环依赖错误如何解决
解决方案
你遇到的是模块级别的循环导入问题,你之前用到的forwardRef和InjectionToken是用来解决依赖注入场景下的循环引用,无法解决当前场景的问题,可按优先级选择以下两种方案处理:
方案1:合并到同一共享模块(最推荐)
既然两个组件有强互相调用关联,直接合并到同一个模块即可从根源消除循环:
- 新建
hello-shared.module.ts - 将
TestLibsHelloWorldComponent和TestLibsHelloMoonComponent都放到该模块的declarations和exports数组中 - 删除原有的两个独立模块,后续需要使用这两个组件的位置直接导入
HelloSharedModule即可。
方案2:动态组件加载(无法合并模块时使用)
如果受架构限制不能合并模块,可移除模块层面的互相导入,通过动态组件API按需加载组件,绕开静态导入的循环检测:
- 首先修改两个模块的配置,移除对方模块的导入,添加入口组件声明(Angular 13+无需配置
entryComponents):
// helloworld.module.ts 修改后 import { CommonModule } from '@angular/common'; import { ModuleWithProviders, NgModule } from '@angular/core'; import { IonicModule } from 'ionic-angular'; import { TestLibsHelloWorldComponent } from './helloworld.component'; @NgModule({ imports: [CommonModule, IonicModule], declarations: [TestLibsHelloWorldComponent], exports: [TestLibsHelloWorldComponent], entryComponents: [TestLibsHelloWorldComponent] // Angular 13及以上版本可删除该行 }) export class TestLibsHelloWorldModule { public static forRoot(): ModuleWithProviders { return { ngModule: TestLibsHelloWorldModule, providers: [], }; } }
hellomoon.module.ts做完全相同的修改即可。
- 修改组件代码,通过动态API加载另一个组件,不需要在模板中直接写组件标签:
以HelloWorld组件加载HelloMoon组件为例:
// helloworld.component.ts import { Component, ComponentFactoryResolver, OnInit, ViewChild, ViewContainerRef } from '@angular/core'; import { TestLibsHelloMoonComponent } from '../hellomoon/hellomoon.component'; @Component({ selector: 'testlibs-helloworld', templateUrl: './helloworld.component.html' }) export class TestLibsHelloWorldComponent implements OnInit { // 绑定模板中的占位容器 @ViewChild('moonContainer', { read: ViewContainerRef }) moonContainer: ViewContainerRef; constructor(private cfr: ComponentFactoryResolver) {} ngOnInit() { // 动态创建HelloMoon组件 const moonFactory = this.cfr.resolveComponentFactory(TestLibsHelloMoonComponent); this.moonContainer.createComponent(moonFactory); } }
修改模板中对应位置的代码,把直接写的组件标签替换为占位容器:
<!-- helloworld.component.html 对应位置替换 --> <ng-template #moonContainer></ng-template>
HelloMoon组件加载HelloWorld组件也做完全相同的修改即可。
该方案模块层面没有互相导入,不会触发AOT的循环依赖检测,组件层面的循环引用Angular运行时可正常处理。
内容的提问来源于stack exchange,提问作者Judson Terrell
相关产品推荐
相关产品推荐

