Виртуальный Скроллер
PrimeNG/VirtualScroller (opens in a new tab)
Виртуальный скроллер - это эффективный способ отображения списков путем отображения небольшого подмножества данных в окне просмотра в любое время.
С чего начать
Подключите модуль
import { VirtualScrollerModule } from 'primeng/virtualscroller';
В .ts файле
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { LazyLoadEvent, SelectItem } from 'primeng/api';
export interface Product {
id?: string;
code?: string;
name?: string;
description?: string;
price?: number;
quantity?: number;
inventoryStatus?: string;
category?: string;
image?: string;
rating?: number;
}
@Component({
selector: 'app-prime-virtualscroller',
templateUrl: './prime-virtualscroller.component.html',
styleUrls: ['./prime-virtualscroller.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PrimeVirtualscrollerComponent implements OnInit {
products: Product[];
virtualProducts: Product[];
sortKey = '';
sortOptions: SelectItem[] = [];
status: string[] = ['OUTOFSTOCK', 'INSTOCK', 'LOWSTOCK'];
productNames: string[] = [
'Bamboo Watch',
'Black Watch',
'Blue Band',
'Blue T-Shirt',
'Bracelet',
'Brown Purse',
'Chakra Bracelet',
'Galaxy Earrings',
'Game Controller',
'Gaming Set',
'Gold Phone Case',
'Green Earbuds',
'Green T-Shirt',
'Grey T-Shirt',
'Headphones',
'Light Green T-Shirt',
'Lime Band',
'Mini Speakers',
'Painted Phone Case',
'Pink Band',
'Pink Purse',
'Purple Band',
'Purple Gemstone Necklace',
'Purple T-Shirt',
'Shoes',
'Sneakers',
'Teal T-Shirt',
'Yellow Earbuds',
'Yoga Mat',
'Yoga Set',
];
constructor() {}
ngOnInit(): void {
this.products = Array.from({ length: 10000 }).map(() => this.generateProduct());
this.sortOptions = [
{ label: 'Cheapest First', value: 'price' },
{ label: 'Expensive First', value: '!price' },
];
}
generateProduct(): Product {
const product: Product = {
id: this.generateId(),
name: this.generateName(),
description: 'Product Description',
price: this.generatePrice(),
quantity: this.generateQuantity(),
category: 'Product Category',
inventoryStatus: this.generateStatus(),
rating: this.generateRating(),
};
return product;
}
generateId() {
let text = '';
let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < 5; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
generateName() {
return this.productNames[Math.floor(Math.random() * Math.floor(30))];
}
generatePrice() {
return Math.floor(Math.random() * Math.floor(299) + 1);
}
generateQuantity() {
return Math.floor(Math.random() * Math.floor(75) + 1);
}
generateStatus() {
return this.status[Math.floor(Math.random() * Math.floor(3))];
}
generateRating() {
return Math.floor(Math.random() * Math.floor(5) + 1);
}
loadCarsLazy(event: LazyLoadEvent) {
// simulate remote connection with a timeout
setTimeout(() => {
//load data of required page
let loadedProducts = this.products.slice(event.first, event.first + event.rows);
//populate page of virtual cars
Array.prototype.splice.apply(this.virtualProducts, [...[event.first, event.rows], ...loadedProducts]);
//trigger change detection
this.virtualProducts = [...this.virtualProducts];
}, 1000);
}
onSortChange() {
if (this.sortKey.indexOf('!') === 0) this.sort(-1);
else this.sort(1);
}
sort(order: number): void {
let products = [...this.products];
products.sort((data1, data2) => {
let value1 = data1.price;
let value2 = data2.price;
let result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;
return order * result;
});
this.products = products;
}
}
Встройте компонент с помощью тэга p-virtualScroller.
<p-virtualScroller [value]="cars" scrollHeight="500px" [itemSize]="150">
<ng-template pTemplate="item" let-car>
Car content
</ng-template>
</p-virtualScroller>
Lazy Loading
[rows]
для указания размера пагинации больше не поддерживается, расчет количества строк идет автоматически, получить значение можно вevent.rows
событияonLazyLoad
По дефолтуpTemplate="loadingItem"
не используется, требуется включить черезoptions.showLoader: true
Для оптимизации рендера рекомендуется использовать функциюtrackBy
. По уникальному ключу (id).Через options.trackBy
List of Products
product.name
product.category
$ product.price
product.inventoryStatus
{{codeExamples.virtualScrollerHTMLExample}}
Prepopulated List
List of Products
product.name
product.category
$ product.price
product.inventoryStatus
Свойства
Name | Type | Default | Description |
---|---|---|---|
delay | number | 250 | Threshold in milliseconds to delay lazy loading during scrolling. |
itemSize | number | null | Height of an item in the list. |
lazy | boolean | false | Defines if data is loaded and interacted with in lazy manner. |
minBufferPx | number | null | Minimum amount of content buffer (in pixels) that the viewport must render. |
maxBufferPx | number | null | Configures how much buffer space to render back up to when it detects that more buffer is required. |
scrollHeight | any | null | Max height of the content area in inline mode. |
style | string | null | Inline style of the component. |
styleClass | string | null | Style class of the component. |
value | array | null | An array of objects to display. |
Конфигурация через свойство [options]
Посмотреть все свойства и методы можно в интерфейсеScrollerOptions
Name | Type | Default | Description |
---|---|---|---|
trackBy | function | null | Function to optimize the dom operations by delegating to ngForTrackBy, default algorithm checks for object identity. |
showLoader | boolean | false | Заменять пустые итемы в списке, во время события загрузки, другим темплейтом |
loading | boolean | false | Показывать перекрывающий темплейт во время загрузки |
События
Name | Parameters | Description |
---|---|---|
onLazyLoad | event.first = First row offset<br>event.rows = Number of rows per page<br> | Callback to invoke in lazy mode to load new data. |
Методы
Name | Parameters | Description |
---|---|---|
scrollToIndex | index: Index of the item.<br>mode: Scroll mode e.g. 'auto' or 'smooth' | Scrolls to the item with the given index. |
Шаблоны
Name | Parameters |
---|---|
header | - |
item | $implicit: Data of the option<br>index: Index of the option<br>count: Count of the options<br>first: First row offset<br>last: Last row offset |
loadingItem | $implicit: Data of the option<br>index: Index of the option<br>count: Count of the options<br>first: First row offset<br>last: Last row offset |
footer | - |
Стилизация
Name | Element |
---|---|
p-virtualscroller | Container element. |
p-virtualscroller-header | Header section. |
p-virtualscroller-footer | Footer section. |
p-virtualscroller-content | Content section. |
p-virtualscroller-list | List element. |