NG3003:库中的 Angular 12 循环依赖项 - Ivy 部分编译模式

Sha*_*ker 5 circular-dependency angular angular-library angular-ivy angular12

我在这里提出一个问题。
\n我有一个ParentComponent它有一个 child ChildComponent,\nchildParentComponent里面有它,所以这里有一个循环。
\n这是我面临的错误:

\n
\xe2\x9c\x96 Compiling with Angular sources in Ivy partial compilation mode.\nERROR: projects/api/src/lib/api.component.ts:3:1\nerror NG3003: One or more import cycles would need to be created to \ncompile this component, which is not supported by the current compiler\nconfiguration.\n\nThe component \'ParentComponent\' is used in the template but importing\nit would create a cycle:\n /lib/child/child.component.ts -> /lib/parent/parent.component.ts -> /lib/child/child.component.ts\n
Run Code Online (Sandbox Code Playgroud)\n

此错误仅发生在 Angular 库中。正如您所看到的, stackblitz示例中没有问题,它只是一个演示。

\n

"compilationMode": "full"这个错误会随着库文件中的设置而消失tsconfig.lib.prod.json,但在这种情况下,我们会失去向后兼容性!\n

\n

官方文档说:

\n
\n

将相互引用的类移动到同一文件中,以避免它们之间的任何导入。\nBlockquote

\n
\n

它确实有效,但这确实是一种丑陋的方法!另外,我们有很多组件,但我们无法做到这一点!\n \n

你能帮我吗?!\n
\n在此输入图像描述

\n

Sha*_*ker 0

好吧,查遍了网上,终于自己解决了!
我使用了这篇文章建议的动态方法:
Angular Circular Dependency with Dynamic Nested Components您可以在 stackblitz
中看到我的解决方案。 我必须在这里再次提到,这个问题(NG3003)仅发生在具有compilationMode的Angular库中。 所以我之前提到的帖子并不是一个完整的解决方案和一个有效的示例。我添加的是一个名为的接口:
partial

ComponentStructure

export interface ComponentStructure {
  type: string;
  content: {
    textContent: string;
    components: ComponentStructure[];
  };
}
Run Code Online (Sandbox Code Playgroud)

components输入到父组件和子组件:

import { Component, Input } from '@angular/core';
import { Base } from '../base';
import { HtmlComponent } from '../child-node.directive';
import { ComponentStructure } from '../component-structure';

@HtmlComponent({ map: ['lib_parent'] })
@Component({
    selector: 'lib-parent',
    templateUrl: './parent.component.html',
  ],
})
export class ParentComponent extends Base {
  @Input() count = 3;
  @Input() set components(_components: ComponentStructure[]) {
    this.childNodes = _components;
  }
  public textContent: string = '';

  constructor() {
    super();
  }

  set content(content: any) {
    this.textContent = content.textContent;
    this.components = content.components;
  }
}
Run Code Online (Sandbox Code Playgroud)

我还改变了Base班级如下:

import { Directive, QueryList, ViewChildren } from '@angular/core';
import { interval } from 'rxjs';
import { take } from 'rxjs/operators';
import { ChildNodeDirective } from './child-node.directive';
import { ComponentStructure } from './component-structure';

@Directive()
export abstract class Base {
  // These are elements that the template will render into the directive
  @ViewChildren(ChildNodeDirective) protected children?: QueryList<any>;
  public childNodes: ComponentStructure[] = [];
  private childrenLoaded = false;

  ngAfterViewInit(): void {
    interval(10)
      .pipe(take(5))
      .subscribe(() => {
        if (!this.childrenLoaded && this.children) {
          this.children.forEach((child: ChildNodeDirective) => {
            child.load();
          });
          this.childrenLoaded = true;
        }
      });
  }
}
Run Code Online (Sandbox Code Playgroud)

我不喜欢的一点是这interval是棘手的部分。但AfterContentChecked原始答案中使用的内容对我不起作用,我必须这样做。
如果您对此有更好的想法,请在评论中告诉我