【问题标题】:NG3003: Angular 12 Circular Dependency in library - Ivy partial compilationModeNG3003:库中的 Angular 12 循环依赖 - Ivy 部分编译模式
【发布时间】:2021-11-23 17:56:52
【问题描述】:

我有一个问题提出here
我有一个ParentComponent 有一个孩子ChildComponent, 并且 child 里面有ParentComponent 所以这里有一个循环。
这是我面临的错误:

✖ Compiling with Angular sources in Ivy partial compilation mode.
ERROR: projects/api/src/lib/api.component.ts:3:1
error NG3003: One or more import cycles would need to be created to 
compile this component, which is not supported by the current compiler
configuration.

The component 'ParentComponent' is used in the template but importing
it would create a cycle:
 /lib/child/child.component.ts -> /lib/parent/parent.component.ts -> /lib/child/child.component.ts

这个错误只发生在 Angular 库中。如您所见,stackblitz 示例中没有问题,这只是一个演示。

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

官方文档说:

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

它确实有效,但这确实是一种丑陋的方式!此外,我们有很多组件,我们就是做不到!

你能帮我吗?!

【问题讨论】:

    标签: angular circular-dependency angular-library angular12 angular-ivy


    【解决方案1】:

    好的,网上找遍了,终于自己解决了!
    我使用了这篇文章建议的动态方法:
    Angular Circular Dependencies with Dynamic Nested Components
    您可以在stackblitz 中查看我的解决方案。
    在这里我必须再次提到,这个问题 (NG3003) 只发生在 Angular 库partial 编译模式中。

    所以我之前提到的帖子不是一个完整的解决方案和一个工作示例。我添加的是一个名为ComponentStructure的接口:

    export interface ComponentStructure {
      type: string;
      content: {
        textContent: string;
        components: ComponentStructure[];
      };
    }
    

    并且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;
      }
    }
    

    我也改变了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;
            }
          });
      }
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-30
      • 2019-03-17
      • 2021-01-22
      • 2019-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多