具有动态嵌套组件的角度循环依赖性

2024-04-20

我在互联网上寻找解决方案,但无济于事(不同情况等),所以请原谅下面的代码转储,我遇到的问题与循环依赖有关。代码转储是为了提供上下文。

旁注:我对 Angular 和 Typescript 相当陌生。

这个概念

当然,我正在尝试构建一组嵌套组件,它们都扩展基类以简化编码。这些组件可以包含彼此的任何子组件。为了加载子组件,基类使用一个指令来决定加载哪个组件来代替它。最好的例子就是想到嵌套<div> and <section> blocks.

这是我的代码:

该指令directive.ts

加载其各自的组件时load()叫做

import { ComponentFactoryResolver, Directive, ViewContainerRef } from '@angular/core';

import { DivComponent } from './div'; // < -- Part of the dependency issues
import { SectionComponent } from './section'; // < -- Part of the dependency issues

@Directive({
    selector: '[child-node]',
})
export class ChildNodeDirective {

    @Input() type: string;
    @Input() content: any;

    constructor(
        private container: ViewContainerRef,
        private resolver: ComponentFactoryResolver,
    ){}

    load(): void {

        let component: Type<any>;

        switch (this.type) {
            case 'div' : component = DivComponent; break;
            case 'section' : component = SectionComponent; break;
        }

        if (component) {
            const factory = this.resolver.resolveComponentFactory(component);
            const componentRef = this.container.createComponent(factory);
            componentRef.instance.content = this.content;
        }

    }

}

基类base.ts

此类是所有组件的基础;

  1. Uses @ViewChildren and ngAfterContentChecked加载其子指令,
  2. Sets childNodes when set content被调用以便组件可以渲染它的<child-node>元素
import { AfterContentChecked, QueryList, ViewChildren } from '@angular/core';

import { ChildNodeDirective } from './directive'; // < -- Part of the dependency issues

export abstract class Base implements AfterContentChecked {

    // These are elements that the template will render into the directive
    public childNodes: {[type: string]: any} = {};

    private childrenLoaded = false;

    @ViewChildren(ChildNodeDirective) protected children?: QueryList<any>;

    ngAfterContentChecked(): void {
        if (!this.childrenLoaded && this.children) {
            this.children.forEach((child: ChildNodeDirective) => {
                child.load();
            });
            this.childrenLoaded = true;
        }
    }

    set content(content: any) {
        this.childNodes = content.childNodes;
    }

}

div 组件div.ts

该组件扩展了基础组件并简单地渲染其子节点

import { Component } from '@angular/core';
import { Base } from './base'; // < -- Part of the dependency issues

@Component({
    selector: 'custom-div',
    templateUrl: './div.html',
})
export class DivComponent extends Base {

    public textContent: string;

    set content(content: any) {

        super.content = content;

        this.textContent = content.text;

    }

}

div 模板div.html


<div>{{ textContent }}</div>

<div *ngFor="let child of childNodes">
  <ng-template child-node [content]="child.content" [type]="child.type"></ng-template>
</div>


TL;DR 问题

所有这一切似乎都有效。我能够生成各种内容和子项的深层嵌套等。我无法谈论代码/实现的“正确性”,但我遇到的唯一问题是循环依赖警告。

WARNING in Circular dependency detected:
div.ts -> base.ts -> directive.ts -> div.ts

WARNING in Circular dependency detected:
section.ts -> base.ts -> directive.ts -> section.ts

请帮我摆脱它们......

SOLUTION

根据 Kai 的最后建议,我创建了一个装饰器来收集元数据以在指令内使用。

改变在directive.ts


export const HtmlElementMap: {component: Type<any>, map: string[]}[] = [];

export function HtmlComponent(config: {map: string[]}) {
    return (target: Type<any>) => {
        ElementMap.push({component: target, map: config.map});
    };
}

@Directive({
    selector: '[child-node]',
})
export class ChildNodeDirective {

    ...

    load(): void {

        let component: Type<any>;

        HtmlElementMap
          .filter(v => v.map.indexOf(this.type) > -1)
          .forEach(
              v => {
                  if (undefined === component) {
                      component = v.component;
                  }
              }
          );

        if (component) {
            const factory = this.resolver.resolveComponentFactory(component);
            const componentRef = this.container.createComponent(factory);
            componentRef.instance.content = this.content;
        }

    }

}

And div.ts以及后续组件


@HtmlComponent({map: ['div']})
@Component({
    selector: 'custom-div',
    templateUrl: './div.html',
})
export class DivComponent extends Base {

   .
   .
   .

}


在我看来,图中的红线就是这里的问题。因此,如果您在运行时注册组件(需要 switch 语句),您可以尝试解决并删除这种依赖关系。例如Base类可以收集所有可用的组件并将它们传递给ChildNodeDirective班级。或者您可以使用服务来注册它们。如果您有有效的 stackblitz 示例,我们可以帮助您编写代码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有动态嵌套组件的角度循环依赖性 的相关文章

随机推荐

  • 如何让这个数组+函数起作用?

    我的阵列需要帮助 我是 C Winforms 的新手 这是我的函数 数组所在的位置 我正在尝试将数组发布到 XML 文件上 Functions static void XML Array string Data Array String x
  • Haskell:hackage Control.Applicative 文章中应用函子法则的描述存在缺陷?:它说 Applicative 决定函子

    我想我发现了一个缺陷黑客文章Control Applicative http hackage haskell org package base 4 8 0 0 docs Control Applicative html 作为对应用函子定律的
  • 在shell脚本中将编码格式设置为java

    我有一个运行我的 Java 应用程序的 shell 脚本 现在我想使用 shell 脚本为我的 java 应用程序指定编码格式 UTF8 任何人都可以提供帮助 我使用的是 mac os Thanks Ganesh Try invoking
  • 使用 PHP 创建 .jpg 文件的下载链接

    我想这应该很容易 我有一个分页图像库 每个图像下方都有一个小链接 上面写着 下载 Comp 这应该允许人们快速将 jpg 文件 带有 PHP 生成的水印 下载到他们的计算机上 现在 我知道我可以直接链接到 jpg 文件 但这需要用户在新窗口
  • 了解 UNIX 命令 xargs

    我对此很困惑 需要一些澄清 示例1 pgrep string xargs ps 示例2 find xargs grep whatever 从示例 1 中 我推测是这样的 搜索作为正在运行的进程名称的一部分的 字符串 并将所有匹配的进程 ID
  • Java 中 & 和 && 有什么区别?

    我一直以为 Java中的运算符用于验证其两个布尔操作数是否为true 以及 运算符用于对两个整数类型进行按位运算 最近我才知道 运算符也可用于验证其布尔操作数是否为true 唯一的区别是即使 LHS 操作数为 false 它也会检查 RHS
  • 如何避免 Entity Framework Core 中的循环导航属性?

    我有一个这样的表架构 CREATE TABLE Categories Id INT IDENTITY 1 1 Name varchar 100 CONSTRAINT PK Category Id PRIMARY KEY Id CREATE
  • iOS 自定义 UITextField 与出口初始化

    I need UITextField几乎没有定制 我创建了新的自定义类 CustomTextField 在IB中我创建了outlet对于我的每一个习惯UITextField 我运行代码 但自定义不起作用 为了进行检查 我在初始化过程中设置了
  • 应该如何构建plot_surface的数组?

    我试图了解如何构建用于plot surface 在Axes3d中 的数组 我尝试构建一个简单的表面来操作这些数组的数据 In 106 x Out 106 array 0 0 0 1 0 0 In 107 y Out 107 array 0
  • VBA 自动化 - 预填充组合盒

    我正在尝试通过 VBA 将数据从 Excel 预填充到本地 Intranet 网站 我已经能够将大部分数据预填充到网站 但我正在努力处理这个组合日期框 请参阅 HTML 代码 div class form group row div
  • 在 switch/case 语句中使用列表中的值作为 case

    我有一个 ArrayList 其中包含以下字符串 name age gender salary 有没有办法可以将 ArrayList 中的值用作 case 表达式 显而易见的答案是否定的 因为 case 表达式必须是常量表达式 但是 我想知
  • 谷歌标签管理器中的自定义事件触发器

    每次我创建自定义触发事件时 它都不会触发 谁能请教一下可能是什么原因 我创建了 gacustomevent 自定义触发器并将其命名为 gaevent 但该事件没有被触发 我想使用数据层中的事件来捕获值 有关如何解决问题的任何建议 从你的问题
  • 如何使着色器淡入某种颜色?

    这是我当前使用的着色器 它通过缓慢降低不透明度来淡化对象 我想褪成紫色 如何才能做到这一点 着色器 frag uniform sampler2D texture uniform float opacity void main vec4 pi
  • 使用 MultiSelect 具有自定义弹出编辑器的 Kendo Grid - 无法获取模型中的选定项目

    所以标题几乎说明了一切 我正在尝试将新的 MultiSelect 小部件合并到网格的自定义弹出编辑器模板中 我正在使用数据属性初始化方法并从远程数据源读取下拉选项 这一切都工作正常 但我无法将所选项目的值放入模型中 当我保存行时 数据数组将
  • 在 Access 中设置子窗体的记录源

    Dim newRS newRS SELECT DISTINCT Grp ID Group Name Group NPI FROM GROUP Forms loclistingfrm LocationListSubFrm RecordSour
  • ESAPI getValidInput 方法的使用

    我无法使用下面的 of 方法ESAPI class java lang String getValidInput java lang String context java lang String input java lang Strin
  • 使用 Javascript 以编程方式制作 Wave

    这是我目前拥有的http jsfiddle net 6GEfr http jsfiddle net 6GEfr 这可行 但我希望它像波浪一样 它应该看起来像真正的波浪 而不是 V 形 你如何逐渐做到这一点 var height 0 setI
  • Eclipse 在启动配置中使用错误的 Maven 依赖项

    我正在开发一个使用 Maven 进行依赖 构建 任何其他操作 项目生命周期管理或其他 的项目 并且我正在使用 Eclipse 进行开发和测试 该项目使用 Vert x 最新 我尝试使用 Hazelcast 进行一些集群管理 但我遇到了 Ha
  • 在什么类型的情况下汇编速度不够快,因此您需要直接的硬件/布尔逻辑解决方案?

    我已经开始通读装配艺术 https nostarch com assembly2 htm 其中有一个关于布尔逻辑的部分 其中指出 当然 使用 Pascal C 甚至汇编语言等语言指定编程问题的解决方案比使用布尔方程指定解决方案要容易得多 因
  • 具有动态嵌套组件的角度循环依赖性

    我在互联网上寻找解决方案 但无济于事 不同情况等 所以请原谅下面的代码转储 我遇到的问题与循环依赖有关 代码转储是为了提供上下文 旁注 我对 Angular 和 Typescript 相当陌生 这个概念 当然 我正在尝试构建一组嵌套组件 它