Wirtualizacja dużych list za pomocą Angular CDK

Zwiększ elastyczność dużych list, implementując przewijanie wirtualne.

Stephen Fluin
Stephen Fluin

Przewijanie listy to jeden z najpopularniejszych wzorców interfejsu – niezależnie od tego, czy chodzi o nieskończone przewijanie kanału w ulubionej witrynie społecznościowej czy korzystanie z panelu firmowego. Gdy przewijane listy stają się bardzo długie (setki, tysiące, a nawet setki tysięcy elementów), może to wpływać na wydajność aplikacji.

Duże listy mogą się wolno ładować, ponieważ aplikacja musi najpierw wczytać i wyrenderować wszystkie dane. Mogą też wolno renderować się i poruszać się po nich , ponieważ każdy element na liście może zawierać dane multimedialne, multimedia i funkcje.

Podczas ładowania lub przewijania strony użytkownicy mogą napotkać problemy, powodując frustrację i porzucenia strony.

Wirtualne przewijanie w Angular za pomocą pakietu Komponenty dla programistów

Podstawową techniką rozwiązywania tych problemów ze skalowaniem jest przewijanie wirtualne. Przewijanie wirtualne daje wrażenie bardzo dużej listy – zapewnia dostęp do paska przewijania o odpowiednim rozmiarze – oraz umożliwia poruszanie się po liście bez konieczności przechowywania przez aplikację całej listy w pamięci lub renderowania jej na stronie.

W Angular przewijanie wirtualne jest obsługiwane przez pakiet CDK (Komponent dla programistów). Modyfikując sposób iteracji list i podając kilka dodatkowych parametrów konfiguracji, funkcja przewijania wirtualnego (CDK) automatycznie zarządza wirtualnym renderowaniem list, co zwiększa wydajność strony i czas reakcji.

Zamiast renderować od razu całą listę, renderowany będzie tylko podzbiór elementów, które mieszczą się na ekranie (oraz mały bufor). W trakcie poruszania się użytkownik oblicza i renderuje nowy podzbiór elementów, a w razie potrzeby ponownie korzysta z dotychczasowego modelu DOM.

W pozostałej części tego posta omawiamy, jak skonfigurować podstawowe przewijanie wirtualne. Pełny przykład działania znajdziesz w tej przykładowej aplikacji:

Konfigurowanie przewijania wirtualnego

Najpierw upewnij się, że aplikacja @angular/cdk została zainstalowana przy użyciu Twojego ulubionego menedżera pakietów. Aby zainstalować ją przy użyciu npm, uruchom w terminalu to polecenie:

npm install --save @angular/cdk

Dodaj ScrollingModule do aplikacji

Po zainstalowaniu dysku CDK zaimportuj z pakietu @angular/cdk/scrolling plik ScrollingModule, który obsługuje przewijanie wirtualne. Następnie dodaj go do tablicy imports w swoim module:

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

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

Tworzenie widocznego obszaru

Aby zobaczyć, jak działa ten pakiet,spróbuj utworzyć komponent z prostą 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);
}

Podczas renderowania aplikacji przeglądarka musi wyrenderować 100 tys. pojedynczych elementów <div>. Może to być odpowiednie w przypadku prostych węzłów tekstowych, ale złożoność powtórzonego szablonu nie będzie dobrze skalowana, a detektory zdarzeń będą znacznie mnożone.

Aby dodać przewijanie wirtualne i uniknąć tych problemów, musisz utworzyć widoczny obszar, pakując listę w element <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, wysokość widocznego obszaru trzeba określić za pomocą standardowego kodu CSS. Musisz też wskazać widoczny obszar jako wskazówkę na temat jej zawartości, określając właściwość itemSize. Moduł wykorzystuje te informacje do określenia, ile elementów ma być jednocześnie przechowywanych w DOM, i jak wyświetlić 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ć całą listę, widoczny obszar dynamicznie identyfikuje i przegląda prawidłowy podzbiór listy dla użytkownika. Teraz, gdy użytkownik wczytuje stronę, plik CDK powinien wyrenderować mieszczący się na ekranie podzbiór listy (z odrobiną bufora), a wszystkie zdarzenia przewijania w widocznym obszarze będą wczytywać i wyrenderować odpowiedni podzbiór listy:

Podzbiory listy renderującej CDK podczas przewijania strony przez użytkownika.

Co dalej

Możliwości przewijania w tle dostępne są znacznie dalej niż w tym podstawowym przykładzie. W przykładowej aplikacji cała lista była w pamięci, ale można ją było pobrać na żądanie w przypadku bardziej złożonych aplikacji. Więcej informacji o innych możliwościach funkcji ScrollingModule i dyrektywie cdkVirtualOf znajdziesz w artykule na temat Scrolling w dokumentacji CDK.

Baner powitalny autorstwa Mr Cup / Fabien Barral z filmu Unsplash.