Angular 中的虚拟列表
创建包含大量数据的列表,而不会使 DOM 变得臃肿
引言
Angular 中的虚拟列表有助于将大量数据加载到视图中,并保持 DOM 的一致性。 这样可以帮助提高 UI 的性能。
背景
当您在 Angular UI 上显示大量数据列表时,您需要实现分页,这需要向服务器发送请求以获取每一页(例如,每页 10 条数据),否则大量数据可能会导致视图性能问题。
Using the Code
该代码使用了虚拟列表的 npm
包。
//install virtuallist npm using command "npm i angular-virtual-list"
//in app.module.ts import following
import { VirtualListModule } from 'angular-virtual-list';
import { Component, OnInit } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { ChangeEvent } from 'angular-virtual-list';
//model class
export class UserModel {
id: number;
name?: string;
contact?: string;
address?:string;
}
@Component({
selector: 'app-virtuallist',
templateUrl: './virtuallist.component.html',
styleUrls: ['./virtuallist.component.scss']
})
export class VirtuallistComponent implements OnInit {
public items: Array<UserModel>=[];
public scrollList: Array<UserModel>=[];
//source for the virtual list
protected items$ = new BehaviorSubject<UserModel[]>(null);
protected buffer: UserModel[] = [];
protected loading: boolean;
// display starting record currently loaded in viewport
startingItem:number;
//display end record currently loaded in viewport
enditem:number;
constructor() {
this.setItem();
}
ngOnInit() {
}
protected fetchMore(event: ChangeEvent) {
this.startingItem=event.start+1;
this.enditem= event.end;
if (event.end == this.buffer.length)
return;
}
public setItem() {
for (var i = 0; i <1000000; i++) {
var item = new UserModel()
item.id = i+1;
item.name = "Name " + (i+1).toString();
item.contact="+1 650-253-0000";
item.address=(1600+i+1).toString()+" Amphitheatre Pkwy,
Mountain View, CA 94043, United States";
this.items.push(item);
}
this.items$.next(this.items)
console.log(this.scrollList)
}
}
HTML 视图如下所示
<h2>Total Record Count: {{items.length}}</h2>
<h2 *ngIf="startingItem">{{startingItem}} to {{enditem}} of {{items.length}} are loaded</h2>
<div class="table-like">
<div class="table-head">
<span style="margin-left: 2px; text-align: center;">Id</span>
<span style="margin-left: 50px; text-align: center;">Name</span>
<span style="margin-left: 60px; text-align: center;">Contact Number</span>
<span style="margin-left: 200px;">Address</span>
</div>
<virtual-list
[source$]="items$"
(update)="scrollList = $event"
(end)="fetchMore($event)" height=400>
<div *ngFor="let item of scrollList" style="display: table-row;">
<span style="display: table-cell; padding: 3px 0 0 2px; text-align: center;">
{{item.id}}</span>
<span style="display: table-cell; padding-left: 36px;text-align: center;">
{{item?.name}}</span>
<span style="display: table-cell; padding-left: 36px;">{{item?.contact}}</span>
<span style="display: table-cell; padding-left: 36px;">{{item?.address}}</span>
</div>
</virtual-list>
</div>
CSS 如下
.table-like{
border: 1px solid #9173ff;
width: 900px;
}
.table-head{
color: #fff;
background-color: #6940ff;
border-bottom: 1px solid #9173ff;
}
每当用户滚动列表时,它将显示固定数量的行,以保持 DOM 的一致性,例如,如果我的服务发送包含 100 万个元素的数组,并且虚拟列表的高度为 500 像素,那么它将一次显示大约 10-14 行数据,并且在滚动时,这些行将更改为下一个或前一个元素。
因此,DOM 中始终只有 10 到 14 行,这保持了性能的稳定。
关注点
您可以在我的 GitHub 仓库中找到完整的代码:https://github.com/cruse07/AngularTest/。
查看 virtuallist 组件。
历史
- 2020 年 2 月 24 日:初始版本