最近在工作中使用angular,組件庫使用ng-zorro-antd,邊學(xué)邊用。在寫表格組件的時(shí)候發(fā)現(xiàn),點(diǎn)擊新增、刪除就,數(shù)據(jù)改變,表格卻沒有更新。
代碼如下:
<a (click)="addRow(item)">新增一列</a>
<nz-table
#basicTable
class="form-table"
[nzBordered]="true"
[nzData]="fields"
[nzShowPagination]="false">
<thead>
<tr>
<th>值的編號(hào)</th>
<th>字段</th>
<th>操作</th>
</tr>
</thead>
<tbody cdkDropList (cdkDropListDropped)="drop($event, fields)">
<!-- <tr *ngFor="let data of fields, let i = index" cdkDrag> -->
<tr *ngFor="let data of basicTable.data, let i = index" cdkDrag>
<td>值{{ i + 1 }}</td>
<td>{{ data.fields }}</td>
<td>
<a (click)="deleteRow(item, i, index, data.$sortOperation)">刪除</a>
</td>
</tr>
</tbody>
</nz-table>
對(duì)表格行數(shù)據(jù)遍歷有2種寫法,如下:
// 寫法1
<tr *ngFor="let data of fields, let i = index" cdkDrag>
// 寫法2
<tr *ngFor="let data of basicTable.data, let i = index" cdkDrag>
如果采用寫法1
寫法是官網(wǎng)示例的寫法之一
點(diǎn)擊新增時(shí),數(shù)據(jù)push進(jìn)去了,但是表格沒有新增一條
addRow(item) {
item.fields.push({
...cloneDeep(fieldsGroup),
add_id: addId,
});
}
但使用如下寫法,點(diǎn)擊新增時(shí),數(shù)據(jù)push進(jìn)去了,但是表格沒有成功顯示新增
addRow(item) {
item.fields = [
...item.groupByFields,
{
...cloneDeep(fieldsGroup),
add_id: addId,
},
];
}
同理刪除的時(shí)候也是如此:
點(diǎn)擊刪除按鈕的時(shí)候,使用splice刪除一行,該數(shù)據(jù)已經(jīng)刪除,但表格頁面數(shù)據(jù)沒有消失
deleteRow(item, index, tableIndex, sortOperation) {
item.fields.splice(index, 1);
}
但是如果使用filter,將過濾后的結(jié)果重新賦值,表格成功刪除一條
deleteRow(item, index, tableIndex, sortOperation) {
item.fields = item.fields.filter(item => item.$sortOperation !== sortOperation);
}
另外,如果只用表格拖拽功能時(shí),寫法1也不能成功拖拽表格順序。
如果采用寫法2
如果采用寫法2,上面的2中寫法都可以實(shí)現(xiàn)效果。
分析
查找ng-zorro-antd源碼,發(fā)現(xiàn)其中是這么寫的:當(dāng)nzData發(fā)生變化的時(shí)候重新渲染。
ngOnChanges(changes: SimpleChanges): void {
if (nzData) {
this.nzData = this.nzData || [];
this.nzTableDataService.updateListOfData(this.nzData);
}
}
查找發(fā)現(xiàn)
當(dāng)Angular檢查組件的輸入屬性以進(jìn)行更改時(shí),它(基本上)===使用臟檢查。對(duì)于數(shù)組,這意味著對(duì)數(shù)組引用(僅)進(jìn)行臟檢查。由于引用沒有改變,ngOnChanges()因此不會(huì)被調(diào)用。
OnChanges只對(duì)輸入的基本數(shù)據(jù)類型起作用,而引用數(shù)據(jù)類型不會(huì)觸發(fā)OnChanges方法。
當(dāng)使用寫法1的時(shí)候,由于是引用數(shù)據(jù)類型,對(duì)表格行數(shù)據(jù)進(jìn)行操作,不會(huì)觸發(fā)OnChanges方法,是不會(huì)觸發(fā)表格組件的重新渲染的,但是重新賦值改變了nzData的引用,會(huì)觸發(fā)OnChanges方法。
ng-zorro-antd官網(wǎng)使用寫法1是因?yàn)槠鋽?shù)據(jù)結(jié)構(gòu)簡單,這個(gè)問題就不會(huì)出現(xiàn)。在自己的工作中,數(shù)據(jù)層級(jí)多,問題出現(xiàn)。