從後臺返回的數據,還有多層子節點,須要一個生成樹的組件,若是直接在頁面上寫循環來拼接感受會很麻煩,由於數據的層級結構不固定。css
參考網上其餘人的方法,整理以下:html
1. 建立一個用於循環迭代的組件,在父組件的元素上綁定須要遞歸的數據和遞歸組件的選擇器。node
<ul class="list-wrapper" [treeData]="circuitList" [originalData]="circuitList" (sendNode)="getCurrentNode($event)" tpl-tree-node></ul>
2. 在遞歸的子組件中接收父組件傳入的數據,並在其模板中調用遞歸組件自身:app
<li *ngFor="let item of treeData"> <a [ngClass]="{'active':item.active}" (click)="getCurrentNode(item)"> <span class="glyphicon mini-icon" *ngIf="item.children" (click)="toggleSubNode(item)" [ngClass]="{'glyphicon-triangle-bottom':item.open,'glyphicon-triangle-right':!item.open}"></span>{{item.name}}</a> <ul *ngIf="item.children" [ngClass]="{'show':item.open,'hidden':!item.open}" [treeData]="item.children" (sendNode)="getCurrentNode($event)" [originalData]="treeData" tpl-tree-node></ul> </li>
子組件的ts代碼ui
import {Component, EventEmitter, Input, Output} from "@angular/core"; @Component({ selector: '[tpl-tree-node]', templateUrl: './tpl-tree-node.component.html', styleUrls: ['./tpl-tree-node.component.css'] }) export class TplTreeNodeComponent { @Input() treeData = []; @Input() originalData; @Output() sendNode: EventEmitter<any> = new EventEmitter<any>(); constructor() { } getCurrentNode(item) { this._formatList(this.originalData); item.active = true; this.sendNode.emit(item); } private _formatList(arr) { arr.forEach(node => { node.active = false; if (node.children) this._formatList(node.children); }); } toggleSubNode(item) { item.open = !item.open; } }
按照以上,樹組件已經能夠正常生成。this
同時在點擊節點時添加一個激活的樣式,取消掉其餘節點的激活樣式,並將節點對應的數據發送到父組件。spa
這裏比較特別的是遞歸組件的選擇器的定義:.net
selector: '[tpl-tree-node]',
3. 與參考連接裏面不一樣的是,多定義了一個@Input() originalData,並在子組件中也綁定了這個屬性。code
這裏是爲了取消其餘樹節點的激活樣式。不綁定這個初始數據的話,節點點擊時,傳入的treeData會變成綁定的item.children的數據。即只處理當前節點並列及如下子節點的狀態。component
4. 從子組建中發送事件到父組件時,一開始沒有在子組件內部迭代的部分也綁定事件,致使部分子節點不會發送事件。
參考連接:https://blog.csdn.net/oneloser/article/details/92086914