被此元件參照的元件、指令或管道,會要求編譯器加入一個會導致匯入循環的匯入。
例如,考慮 Parent 在其範本中參照 Child 的情境:
parent.ts
import {Component} from '@angular/core';
import {Child} from './child';
@Component({
selector: 'app-parent',
imports: [Child],
template: '<app-child/>',
})
export class Parent {}
child.ts
import {Component, inject} from '@angular/core';
import {Parent} from './parent';
@Component({
selector: 'app-child',
template: 'The child!',
})
export class Child {
private parent = inject(Parent);
}
由於 Child 在其建構函式中參照了 Parent,已經存在從 child.ts 到 parent.ts 的匯入。
HELPFUL: 父元件的範本包含 <child></child>。
因此,此範本產生的程式碼必須包含對 Child 類別的參照。
為了建立這個參照,編譯器必須加入從 parent.ts 到 child.ts 的匯入,這會造成匯入循環:
parent.ts -> child.ts -> parent.ts
遠端範圍界定(Remote Scoping)
如果你使用 NgModule,為了避免加入會造成循環的匯入,系統會在宣告負責串連依賴之元件的 NgModule 類別中加入額外的程式碼。
這稱為「remote scoping」。
程式庫
不幸的是,「remote scoping」程式碼具有副作用,會阻礙搖樹優化,因此不能用在程式庫中。
所以,在使用 "compilationMode": "partial" 設定建置程式庫時,任何會需要循環匯入的元件都會引發此 NG3003 編譯器錯誤。
除錯方式
將會產生的循環會顯示為錯誤訊息的一部分。 例如:
The component Child is used in the template but importing it would create a cycle:
/parent.ts -> /child.ts -> /parent.ts
請用它來找出被參照的元件、管道或指令如何反向依賴到正在編譯的元件。 以下是一些修正問題的想法:
- 嘗試重新安排你的依賴關係以避開循環。 例如,使用儲存在獨立檔案中的中介介面,讓兩個相依的檔案都能匯入它,而不造成匯入循環。
- 把互相參照的類別移到同一個檔案中,以避開它們之間的任何匯入。
- 如果匯入的宣告只用作型別,把匯入陳述式改為僅型別匯入(使用
import type語法),因為僅型別匯入不會造成循環。