javascript - Angular6管道过滤器在大型阵列上运行缓慢
问题描述
我有这个过滤器,它从一个大数组中返回一个项目的子集(这个数组中大约有 500 个项目)
import { Injectable, Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'searchFilter'
})
@Injectable()
export class FilterArrayPipe implements PipeTransform {
transform(value: any, ...args): any {
// tslint:disable-next-line:no-unused-expression
console.log(value, args);
if ( typeof args[0] === 'undefined') {
return value;
} else if (value) {
return value.filter(item => {
// tslint:disable-next-line:prefer-const
for (let key in item) {
if ((typeof item[key] === 'string' || item[key] instanceof String) &&
(item[key].toUpperCase().indexOf(args[0].toUpperCase()) !== -1)) {
return true;
}
}
});
}
}
}
每当我在文本框中键入时,字符实际显示在框中需要几秒钟,再过几秒钟返回更新列表以返回搜索项。
我尝试添加slice:0:10
以限制屏幕上的项目数量,但它有同样的问题,所以我猜测缓慢是由于大数组而不是屏幕渲染。
我已经和后端开发人员谈过了,由于这个数组被其他人使用,他不会修改它。我能做些什么来提高性能?
编辑:包括html代码:
<form *ngFor='let subarray of array | searchFilter: filterText | slice:0:20 ; let i = index;' #form="ngForm" (ngSubmit)="Save(form)">
<fieldset>
<input type="text" name="country" [ngModel]="subarray.country ">
<input type="number" name="number" [ngModel]="subarray.number ">
............about 24 input fileds in total ..............
</fieldset>
</form>
解决方案
您应该尝试一些性能改进:
对 ngForOf 使用 trackBy-function
使用为指令提供一个trackBy
函数ngForOf
,例如通过索引跟踪所有 DOM 元素:
// template:
<div *ngFor="let subarray of array; trackBy:trackByIndex">
...
</div>
// component:
public trackByIndex(index: number, value: any)
{
return index;
}
不要使用管道过滤数据 (用于不纯管道)
不要使用管道过滤大型数组,因为每次为组件运行 changedetection 时都会调用它。
例如,如果搜索输入发生变化,您可以过滤大数组:
// component:
public originalData: any[] = [...];
public filteredData: any[] = this.originalData;
// ...
public filterData(searchString: string)
{
this.filteredData = this.originalData.filter(item => {
// your filter logic
})
}
通过可搜索的字符串丰富您的每个项目
通过可搜索的字符串丰富数组中的每个项目。如果您想搜索一个项目的所有值,只需映射一次数组并将一个新键附加到该项目,如:
this.originalData = this.dataService.getData().map(item => {
return {
...item,
searchableString: Object.values(item).join(':'),
}
})
这可以防止您在过滤时遍历每个项目。您只需在该属性内搜索输入字符串。
item.searchableString.indexOf(input) > -1
其他技术
- 去抖动用户搜索输入
- 使用 BehaviorSubject 过滤服务内的数据,
ChangeDetectionStrategy.OnPush
并将数据作为列表组件的输入
边注
请记住,Angular 开发模式下的性能远低于生产模式。在开发模式下,每个更改检测都会运行两次。AOT-mode也会带来很多性能提升。
推荐阅读
- c++ - 查找用于提升多精度 uint512_t 的 First Set 指令 (ffs)
- typescript - 我如何禁用/处理初始化,toJSON
- uiscrollview - 为什么滚动时 UIScrollView 会颠簸
- kotlin - 我需要手动停止处理程序吗?
- java - 选择时如何将颜色箭头图标更改为 JMenu
- javascript - nodejs中连接模块的顺序是什么?
- c++ - 信号:分段错误 (11) 信号代码:无效权限 (2)
- c - 用于打印数组中元素位置的C函数不起作用
- python - 我在 python 中的代码因未知原因重复出现
- java - Springboot JAR 文件 500s