Угловой рекурсивный компонент с * ngFor и асинхронным каналом зацикливается - PullRequest
0 голосов
/ 05 октября 2018

Я пытался создать динамическое дерево контента в угловых.Как ниже.

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 голосов
/ 05 октября 2018

Давайте посмотрим на рендеринг узлов, начиная с родительского узла.

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*/
}

Вам нужно будет назначить родительский узел, используя алгоритм ширины вначале.

Приведенный ниже шаблон теперь сможет отображать созданное вами дерево.Он получит самый верхний узел и отобразит имя.

Используя and * ngTemplateOutlet, мы можем отправить список дочерних узлов для рендеринга, установив неявное значение $ контекста.В 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

...