Wirtualizacja dużych list za pomocą Angular CDK

Zwiększanie elastyczności dużych list przez wdrożenie przewijania wirtualnego.

Stephen Fluin
Stephen Fluin

Przewijana lista to obecnie jeden z najpopularniejszych wzorców interfejsu, niezależnie od tego, czy przeglądasz przewijanie nieskończone w ulubionych mediach społecznościowych, czy poruszasz się po panelu firmowym. Gdy przewijane listy stają się bardzo długie (setki, tysiące lub setki tysięcy elementów), wydajność aplikacji może się pogorszyć.

Wczytywanie dużych list może być powolne, ponieważ aplikacja musi najpierw wczytać i wyrenderować wszystkie dane. Mogą też wolno się renderować i utrudniać nawigację , ponieważ każdy element na liście może zawierać dane rozszerzone, multimedia i funkcje.

Użytkownicy mogą mieć problemy z wczytywaniem lub przewijaniem strony, co może prowadzić do frustracji i opuszczenia strony.

Przewijanie wirtualne w Angularze za pomocą pakietu Component Dev Kit

Przewijanie wirtualne to podstawowa technika używana do rozwiązywania tych problemów ze skalowaniem. Przewijanie wirtualne daje wrażenie bardzo dużej listy, ponieważ zapewnia pasek przewijania o odpowiednim rozmiarze i możliwość poruszania się po liście bez konieczności przechowywania całej listy w pamięci aplikacji lub renderowania jej na stronie.

W Angularze przewijanie wirtualne jest dostępne w pakiecie Component Dev Kit (CDK). Zmieniając sposób iteracji po listach i podając kilka dodatkowych parametrów konfiguracji, możesz sprawić, że wirtualne przewijanie CDK będzie automatycznie zarządzać wirtualnym renderowaniem list, co poprawi wydajność i czas reakcji strony.

Zamiast renderować całą listę naraz, renderowany jest tylko podzbiór elementów, które mieszczą się na ekranie (plus niewielki bufor). Gdy użytkownik się przemieszcza, obliczany i renderowany jest nowy podzbiór elementów, który w razie potrzeby ponownie wykorzystuje istniejący DOM.

W dalszej części tego posta dowiesz się, jak skonfigurować podstawowe przewijanie wirtualne. Pełny, działający przykład znajdziesz w tej przykładowej aplikacji:

Konfigurowanie przewijania wirtualnego

Najpierw upewnij się, że masz zainstalowane narzędzie @angular/cdk przy użyciu ulubionego menedżera pakietów. Aby zainstalować go za pomocą npm, uruchom w terminalu to polecenie:

npm install --save @angular/cdk

Dodawanie ScrollingModule do aplikacji

Po zainstalowaniu pakietu CDK zaimportuj z pakietu @angular/cdk/scrolling moduł ScrollingModule, który obsługuje przewijanie wirtualne. Następnie dodaj go do tablicy importów modułu:

import {ScrollingModule} from '@angular/cdk/scrolling';

...
imports: [
  ScrollingModule
...
]
...

Tworzenie widocznego obszaru

Aby zobaczyć, jak działa pakiet,spróbuj utworzyć komponent z listą liczb od 0 do 99 999:

@Component({
  template: `<div *ngFor="let item of list">{{item}}</div>`
})
export class ScrollComponent {
  list = Array.from({length: 100000}).map((_, i) => i);
}

Gdy przeglądarka renderuje aplikację, musi wyrenderować 100 000 pojedynczych elementów <div>. Może to być dobre w przypadku podstawowych węzłów tekstowych, ale wszelkie złożone elementy w powtarzanym szablonie nie skalują się dobrze, a liczba detektorów zdarzeń znacznie wzrośnie.

Aby dodać wirtualne przewijanie i uniknąć tych problemów, musisz utworzyć widoczny obszar, umieszczając listę w elemencie <cdk-virtual-scroll-viewport>:

@Component({
  template: `<cdk-virtual-scroll-viewport>
    <div *ngFor="let item of list">{{item}}</div>
    </cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
  list = Array.from({length: 100000}).map((_, i) => i);
}

Ponieważ ScrollingModule dynamicznie renderuje podzbiory listy, musisz określić wysokość widocznego obszaru za pomocą standardowego kodu CSS. Musisz też podać wskazówkę dotyczącą zawartości widocznego obszaru, określając itemSize. Moduł używa tych informacji, aby określić, ile elementów ma być przechowywanych w DOM w danym momencie i jak renderować pasek przewijania o odpowiednim rozmiarze.

@Component({
  template: `<cdk-virtual-scroll-viewport itemSize="18" style="height:80vh">
    <div *ngFor="let item of list">{{item}}</div>
    </cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
  list = Array.from({length: 100000}).map((_, i) => i);
}

Na koniec przekonwertuj *ngFor na *cdkVirtualFor:

@Component({
  template: `<cdk-virtual-scroll-viewport itemSize="18" style="height:80vh">
    <div *cdkVirtualFor="let item of list">{{item}}</div>
    </cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
  list = Array.from({length: 100000}).map((_, i) => i);
}

Zamiast iterować po całej liście, widoczny obszar dynamicznie identyfikuje i iteruje po odpowiednim podzbiorze listy dla użytkownika. Teraz, gdy użytkownik wczyta stronę, CDK powinien wyrenderować podzbiór listy, który mieści się na ekranie (plus niewielki bufor), a wszelkie zdarzenia przewijania w widocznym obszarze wczytują i renderują odpowiedni podzbiór listy:

CDK renderuje podzbiory listy, gdy użytkownik przewija ekran.

Dalsze kroki

Możliwości wirtualnego przewijania w CDK wykraczają daleko poza ten podstawowy przykład. W przykładowej aplikacji cała lista była w pamięci, ale w bardziej złożonych aplikacjach można ją pobierać na żądanie. Więcej informacji o innych możliwościach ScrollingModule i dyrektywy cdkVirtualOf znajdziesz w opisie Scrolling w dokumentacji CDK.