Angular - 加速过滤和显示 *ngFor
Angular - Speed up filtering and display of *ngFor
我有一个用户列表(目前大约有 450 个),我使用 onValueChanges 订阅和 javascript 过滤方法进行过滤。这似乎很慢。我相信它应该更快,但不确定是对象的实际过滤还是重新渲染 html 很慢。
当我在 stackBlitz 中重新创建它时,它非常快,所以我不确定为什么在我的项目中显示过滤的项目很慢。
实物略有不同,但相差不大
address: null
emailAddress: "fred.bloggs@example.com"
employeeId: 1
extraPhoneNumber: null
fullName: "Administrator Account"
jobTitle: "Learning Administrator"
personId: 52
phoneNumber: "01234567890"
photograph: null
searchTerms: "Administrator Account, 1, Learning Administrator"
totalAlerts: 0
totalCompleted: 0
totalMandatory: 0
totalOverdue: 0
totalToDo: 0
我的Html
<form class="" [formGroup]="myForm">
<input type="text" class="input learningItemsSearch" placeholder="Search My Team"
name="searchString" formControlName="searchString" />
</form>
<cdk-virtual-scroll-viewport itemSize="70" class="viewport">
<div *ngFor="let user of filteredUsers">
<table>
<tbody>
<tr>
<td colspan="3">
{{ user.fullName }}
</td>
<td colspan="3">
{{ user.jobTitle }}
</td>
<td colspan="3">
{{ user.emailAddress }}
</td>
<td colspan="3">
{{ user.phoneNumber }}
</td>
</tr>
</tbody>
</table>
</div>
</cdk-virtual-scroll-viewport>
我的组件
this.myForm.valueChanges.pipe(
debounceTime(400),
distinctUntilChanged(),
tap((value: any) => {
let searchTerm = value.searchString;
this.filteredUsers = this.users.filter((userName) =>
userName.searchTerms
.toLowerCase()
.indexOf(searchTerm.toLowerCase()) !== -1)
})
).subscribe( );
这是筛选对象数组的最有效方法吗?是否还有其他原因导致它似乎需要一些时间才能显示在屏幕上? html 没有什么太复杂的。我正在使用 cdk-virtual-scroll 看看它是否会加载得更快,但没有它它也很慢。
编辑: 我忘了使用 *cdkVirtualFor 而不是 *ngFor。现在快多了。我认为添加下面提到的 trackby 也有帮助。
您可能会看到使用 trackBy
功能 https://angular.io/api/core/TrackByFunction 的渲染加速。将以下函数添加到您的组件中:
public trackById = (_: number, item: any) => item.id; // or userId, whatever is the unique identifier
然后修改你的模板:
<div *cdkVirtualFor="let user of filteredUsers; trackBy:trackById">
我认为 2 可能会导致明显的性能变化(当然 3 很长)
1.保留与 -1
的比较
// before: userName.searchTerms.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1
userName.searchTerms.toLowerCase().includes(searchTerm.toLowerCase())
2。看起来很奇怪,你想要每个用户一个 table,你确定它不应该是一个 table 与用户行行吗?
<tr *ngFor="let user of filteredUsers">
<td colspan="3">{{ user.fullName }}</td>
<td colspan="3">{{ user.jobTitle }}</td>
<td colspan="3">{{ user.emailAddress }}</td>
<td colspan="3">{{ user.phoneNumber }}</td>
</tr>
3。 JohnD
的回答中提到的 trackBy 的使用
4.订阅控件而不是整个表单
this.myForm.controls.searchString.valueChanges
.pipe(
debounceTime(400),
distinctUntilChanged(),
tap((searchTerm: string) => {
我有一个用户列表(目前大约有 450 个),我使用 onValueChanges 订阅和 javascript 过滤方法进行过滤。这似乎很慢。我相信它应该更快,但不确定是对象的实际过滤还是重新渲染 html 很慢。
当我在 stackBlitz 中重新创建它时,它非常快,所以我不确定为什么在我的项目中显示过滤的项目很慢。
实物略有不同,但相差不大
address: null
emailAddress: "fred.bloggs@example.com"
employeeId: 1
extraPhoneNumber: null
fullName: "Administrator Account"
jobTitle: "Learning Administrator"
personId: 52
phoneNumber: "01234567890"
photograph: null
searchTerms: "Administrator Account, 1, Learning Administrator"
totalAlerts: 0
totalCompleted: 0
totalMandatory: 0
totalOverdue: 0
totalToDo: 0
我的Html
<form class="" [formGroup]="myForm">
<input type="text" class="input learningItemsSearch" placeholder="Search My Team"
name="searchString" formControlName="searchString" />
</form>
<cdk-virtual-scroll-viewport itemSize="70" class="viewport">
<div *ngFor="let user of filteredUsers">
<table>
<tbody>
<tr>
<td colspan="3">
{{ user.fullName }}
</td>
<td colspan="3">
{{ user.jobTitle }}
</td>
<td colspan="3">
{{ user.emailAddress }}
</td>
<td colspan="3">
{{ user.phoneNumber }}
</td>
</tr>
</tbody>
</table>
</div>
</cdk-virtual-scroll-viewport>
我的组件
this.myForm.valueChanges.pipe(
debounceTime(400),
distinctUntilChanged(),
tap((value: any) => {
let searchTerm = value.searchString;
this.filteredUsers = this.users.filter((userName) =>
userName.searchTerms
.toLowerCase()
.indexOf(searchTerm.toLowerCase()) !== -1)
})
).subscribe( );
这是筛选对象数组的最有效方法吗?是否还有其他原因导致它似乎需要一些时间才能显示在屏幕上? html 没有什么太复杂的。我正在使用 cdk-virtual-scroll 看看它是否会加载得更快,但没有它它也很慢。
编辑: 我忘了使用 *cdkVirtualFor 而不是 *ngFor。现在快多了。我认为添加下面提到的 trackby 也有帮助。
您可能会看到使用 trackBy
功能 https://angular.io/api/core/TrackByFunction 的渲染加速。将以下函数添加到您的组件中:
public trackById = (_: number, item: any) => item.id; // or userId, whatever is the unique identifier
然后修改你的模板:
<div *cdkVirtualFor="let user of filteredUsers; trackBy:trackById">
我认为 2 可能会导致明显的性能变化(当然 3 很长)
1.保留与 -1
// before: userName.searchTerms.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1
userName.searchTerms.toLowerCase().includes(searchTerm.toLowerCase())
2。看起来很奇怪,你想要每个用户一个 table,你确定它不应该是一个 table 与用户行行吗?
<tr *ngFor="let user of filteredUsers">
<td colspan="3">{{ user.fullName }}</td>
<td colspan="3">{{ user.jobTitle }}</td>
<td colspan="3">{{ user.emailAddress }}</td>
<td colspan="3">{{ user.phoneNumber }}</td>
</tr>
3。 JohnD
的回答中提到的 trackBy 的使用4.订阅控件而不是整个表单
this.myForm.controls.searchString.valueChanges
.pipe(
debounceTime(400),
distinctUntilChanged(),
tap((searchTerm: string) => {