低复杂度多选框设计与实现

7次阅读

共计 2351 个字符,预计需要花费 6 分钟才能阅读完成。

引言
还是性能的问题,数据量大的时候,特别得卡。

上算法课,也没找到一种性能很优的算法,最终使用 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();
// 请求后台更新计算机组
}
ViewChild – Angular.io
Angular 官网说 ViewChild 用于视图查询,我理解就是把用到的组件注进来,和组件的交互不仅限于输入输出,还可以调用组件对外暴露的方法。
总结
当编码已经不成问题的时候,我们真正可以当语言为工具,通过我们的思考,构造一个又一个实用的设计。

正文完
 0