引言
还是性能的问题,数据量大的时候,特别得卡。
上算法课,也没找到一种性能很优的算法,最终使用Map
重新设计了一下,并使用原生的checkbox
,性能有极大地提升,用户感觉不出任何卡顿。
优化实践
原组件性能分析
<nz-checkbox-wrapper style="width: 100%;" (nzOnChange)="change($event)">
<div nz-row>
<div nz-col nzSpan="4" *ngFor="let host of hostListValues">
<label nz-checkbox [nzValue]="host.value"
[(ngModel)]="host.checked">{{host.label}}</label>
</div>
</div>
</nz-checkbox-wrapper>
this.hostService.getAllHosts().subscribe((hosts) => {
this.hostListValues = [];
// 获取主机数量
const length = hosts.length;
// 使用主机信息构造多选框绑定数据
for (let index = 0; index < length; index++) {
this.hostListValues.push({
label: hosts[index].name,
value: hosts[index],
checked: HostCheckboxComponent.existIn(hosts[index], this._hostList)
});
}
});
- 根据计算机列表构造符合规范的数组(每次循环都需要判断是否选中)。
-
html
中ngFor
。 - 每点击一次,就输出一次
nzOnChange
事件,因为该事件的参数是当前选中的计算机列表,所以应该也进行循环了。
使用原生checkbox
使用原生的checkbox
,我们就不需要再去循环构建符合ng zorro
要求格式的数据了,直接就把计算机列表传给页面。
<nz-row>
<nz-col *ngFor="let host of hosts" [nzSpan]="4">
<label>
<input type="checkbox">
{{ host.name }}
</label>
</nz-col>
</nz-row>
默认选中的设计
原来的默认选中复杂度太高。
假设2000
台计算机,100
个默认选中的,最终执行次数就是2000 * 100
。
for 计算机列表
for 默认选中计算机列表
怎样降低复杂度呢?
最终想到了使用Map
,毕竟Map
查询的复杂度是要比自己for
循环低的多的。设计一个checkedMap
,该Map
中存储了所有被选中的主机的id
。
/**
* 计算机选中的Map存储
*/
public checkedMap: Map<number, boolean>;
<nz-row>
<nz-col *ngFor="let host of hosts" [nzSpan]="4">
<label>
<input type="checkbox" (change)="syncHostCheckedMap(host.id)" [checked]="checkedMap.get(host.id)">
{{ host.name }}
</label>
</nz-col>
</nz-row>
再分析一下,2000
台计算机,100
台默认选中的,因为Native Map
的高性能,应该能提升部分性能。
组件输出
@Output()
hostCheck = new EventEmitter<Array<Host>>();
因为多选框写成了组件,组件其实并不知道用我的页面什么时候要我的数据,所以使用事件输出的,当用户选中的内容有变化时,我就for
循环一次所有的计算机,然后把选中的输出出去。
现在则是写一个public
方法,供外部调用。
/**
* 获取所有选中的计算机列表
* 供外部调用
*/
public getAllCheckedHostList(): Array<Host> {
// 初始化计算机列表
const hostList: Array<Host> = new Array<Host>();
// 遍历选中的Map
this.checkedMap.forEach((value, key) => {
// 遍历计算机列表
this.hosts.forEach((host) => {
// 如果符号位,添加到列表中
if (host.id === key) {
hostList.push(host);
}
});
});
// 返回
return hostList;
}
怎么调的呢?以下是示例代码:
<app-host-checkbox #hostCheckbox [primaryHostList]="primaryHostList"></app-host-checkbox>
/**
* 获取HostCheckboxComponent组件
*/
@ViewChild('hostCheckbox')
private hostCheckbox: HostCheckboxComponent;
/**
* 计算机组更新方法
* @param hostGroup 计算机组
*/
public update(hostGroup: HostGroup): void {
// 从组件中拿去选中的计算机的列表
hostGroup.hostList = this.hostCheckbox.getAllCheckedHostList();
// 请求后台更新计算机组
}
Angular
官网说ViewChild
用于视图查询,我理解就是把用到的组件注进来,和组件的交互不仅限于输入输出,还可以调用组件对外暴露的方法。
总结
当编码已经不成问题的时候,我们真正可以当语言为工具,通过我们的思考,构造一个又一个实用的设计。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。