具有* ngFor和异步管道的Angular递归组件进入循环

时间:2018-10-05 13:31:03

标签: angular recursion tree observable ngfor

我试图创建一个有角度的动态内容树。像下面。

vehicles
  - cars
     - vw
       - golf
       - passat
     - ford
       - fiesta
     - toyota
  - Buses
    - volvo
    - Scania
Animals
  - carnivorous
    - Lion
    - tiger
  - Herbivorous
    - Cow
    - Horse

我有一个内容树组件和一个树节点组件。我试图根据章节数在树中动态创建子代。由于DocRootNode是可观察的,因此我必须在代码中使用异步管道。并且我递归地使用树节点来创建动态树。

content-tree.html:

<tree-node *ngFor="let docChildNode of DocRootNode$ | async"
                 [node]="docChildNode">
</tree-node>

tree-node.html:

  <div class="children" *ngIf="node.children">
    <tree-node *ngFor="let childDocNode of node.children" [node]="childDocNode" >
    </tree-node>
  </div>

一切正常。但是我发现一个问题,在后台递归循环进行。例如:我添加了[ngClass] = "{ isActive: isActive(node) }",在isActive函数中,我做了一个控制台日志,发现该日志正在循环中。我找不到原因。我是Angular的新手。我们非常感谢您的帮助。

更新日志。数字是节点

tree-node.component.ts:78 This one 4
tree-node.component.ts:78 This one 6
tree-node.component.ts:78 This one 3
tree-node.component.ts:78 This one 3-0
tree-node.component.ts:78 This one 3-0-0
tree-node.component.ts:78 This one 3-0-0-0
tree-node.component.ts:78 This one 3-0-0-2
tree-node.component.ts:78 This one 3-0-1
tree-node.component.ts:78 This one 3-0-2
tree-node.component.ts:78 This one 3-0-2-0
tree-node.component.ts:78 This one 3-0-2-1
tree-node.component.ts:78 This one 3-0-2-2
tree-node.component.ts:78 This one 3-1-0-0
tree-node.component.ts:78 This one 3-1-1
tree-node.component.ts:78 This one 3-1-1-0

tree-node.component.ts:78 This one 4
tree-node.component.ts:78 This one 6
tree-node.component.ts:78 This one 3
tree-node.component.ts:78 This one 3-0
tree-node.component.ts:78 This one 3-0-0
tree-node.component.ts:78 This one 3-0-0-0
tree-node.component.ts:78 This one 3-0-0-2
tree-node.component.ts:78 This one 3-0-1
tree-node.component.ts:78 This one 3-0-2
tree-node.component.ts:78 This one 3-0-2-0
tree-node.component.ts:78 This one 3-0-2-1
tree-node.component.ts:78 This one 3-0-2-2
tree-node.component.ts:78 This one 3-1-0-0
tree-node.component.ts:78 This one 3-1-1
tree-node.component.ts:78 This one 3-1-1-0

tree-node.component.ts:78 This one 4
tree-node.component.ts:78 This one 6
tree-node.component.ts:78 This one 3
tree-node.component.ts:78 This one 3-0
tree-node.component.ts:78 This one 3-0-0
tree-node.component.ts:78 This one 3-0-0-0
tree-node.component.ts:78 This one 3-0-0-1
tree-node.component.ts:78 This one 3-0-0-2
tree-node.component.ts:78 This one 3-0-1
tree-node.component.ts:78 This one 3-0-2
tree-node.component.ts:78 This one 3-0-2-0
tree-node.component.ts:78 This one 3-0-2-1
tree-node.component.ts:78 This one 3-0-2-2
tree-node.component.ts:78 This one 3-1-1
tree-node.component.ts:78 This one 3-1-1-0

Adjo

1 个答案:

答案 0 :(得分:1)

让我们看看从父节点开始渲染节点。

export interface TreeNode<T> {
    value: T;
    children: Array<TreeNode<T>>;
    parent?: TreeNode<T>;
}

给出您的输入,您将渲染此树。

vehicles
  - cars
     - vw
       - golf
       - passat

{
    value: 'vehicles',
    children: [
        {
            value: 'cars',
            children: [
                {
                    value: 'vw',
                    children: [
                        {
                            value: 'golf',
                            children: [],
                            parent: /* linked to 'vw' node */
                        },
                        {
                            value: 'passat',
                            children: [],
                            parent: /* linked to 'vw' node */
                        }
                    ],
                    parent: /* linked to 'cars' node */
                }
            ]
        }
    ],
    parent: undefined /*or null*/
}

您将需要使用广度优先算法分配父节点。

下面的模板现在将能够渲染您创建的树。 它将获得最顶部的节点并显示名称。

使用和* ngTemplateOutlet,我们可以通过设置上下文的$ implicit值将子节点列表发送到进行渲染。 然后,在ng模板中,我们将具有一些逻辑来渲染名称,并在有子元素的情况下递归调用相同的ng模板。这将创建您的树。

您将必须添加适合您的应用程序的正确样式。

<div *ngIf="tree?.value">
    <h2> {{tree.value.name}}</h2>
</div>
<div *ngIf="tree?.children">
    <ng-template #recursiveList let-list>
        <div *ngFor="let node of list">
            <h5>{{node.value.name}}</h5>
            <div *ngIf="node.children.length > 0">
                <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: node.children }"></ng-container>
            </div>
        </div>
    </ng-template>
    <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: tree.children }"></ng-container>
</div>

文档: https://angular.io/api/common/ngTemplateOutlet https://angular.io/guide/structural-directives