Virtualiser de grandes listes avec le CDK Angular

Améliorez la réactivité des longues listes en implémentant le défilement virtuel.

Stephen Fluin
Stephen Fluin

La liste déroulante est l'un des modèles d'UI les plus courants aujourd'hui, que vous parcouriez un flux à défilement infini sur votre site de réseau social préféré ou que vous naviguiez dans un tableau de bord d'entreprise. Lorsque les listes à faire défiler deviennent très longues (des centaines, des milliers ou des centaines de milliers d'éléments), les performances de l'application peuvent en souffrir.

Le chargement de longues listes peut être lent, car l'application doit charger et afficher toutes les données à l'avance. L'affichage et la navigation peuvent également être lents, car chaque élément de la liste peut comporter des données, des contenus multimédias et des fonctionnalités riches.

Les utilisateurs peuvent rencontrer des problèmes lorsqu'ils chargent ou font défiler la page, ce qui peut entraîner de la frustration et un abandon de la page.

Défilement virtuel dans Angular avec le kit de développement de composants

Le défilement virtuel est la principale technique utilisée pour résoudre ces problèmes d'échelle. Le défilement virtuel donne l'impression d'une très longue liste (en fournissant une barre de défilement de taille appropriée) et la possibilité de parcourir la liste sans que l'application ait besoin de conserver toute la liste en mémoire ni de l'afficher sur la page.

Dans Angular, le défilement virtuel est fourni par le kit de développement de composants (CDK). En modifiant la façon dont vous itérez dans les listes et en fournissant quelques paramètres de configuration supplémentaires, le défilement virtuel de la CDK gérera automatiquement le rendu virtuel de vos listes, ce qui améliorera les performances et la réactivité de la page.

Au lieu d'afficher la liste entière à la fois, seul un sous-ensemble des éléments qui s'affichent à l'écran (plus un petit tampon) est affiché. À mesure que l'utilisateur navigue, un nouveau sous-ensemble d'éléments est calculé et affiché, en réutilisant le DOM existant si nécessaire.

Le reste de cet article explique comment configurer le défilement virtuel de base. Vous pouvez voir un exemple complet dans cette application exemple :

Configurer le défilement virtuel

Assurez-vous d'abord d'avoir installé @angular/cdk à l'aide de votre gestionnaire de paquets favori. Pour l'installer à l'aide de npm, exécutez la commande suivante dans le terminal :

npm install --save @angular/cdk

Ajouter ScrollingModule à votre application

Une fois le CDK installé, importez ScrollingModule, qui gère le défilement virtuel, à partir du package @angular/cdk/scrolling. Ajoutez-le ensuite au tableau "imports" de votre module:

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

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

Créer une fenêtre d'affichage

Pour voir comment fonctionne le package, essayez de créer un composant avec une liste simple de nombres compris entre 0 et 99 999 :

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

Lorsque le navigateur affiche l'application, il doit afficher 100 000 éléments <div> individuels. Cela peut convenir pour les nœuds de texte simples, mais toute complexité du modèle répété ne sera pas bien évolutive, et les écouteurs d'événements seront multipliés de manière significative.

Pour ajouter le défilement virtuel et éviter ces problèmes, vous devez créer un viewport en encapsulant la liste dans un élément <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);
}

Étant donné que ScrollingModule affiche de manière dynamique les sous-ensembles de la liste, vous devez spécifier la hauteur de la fenêtre d'affichage via le CSS standard. Vous devez également donner un indice au viewport sur son contenu en spécifiant le itemSize. Le module utilise ces informations pour déterminer le nombre d'éléments à conserver dans le DOM à un moment donné et comment afficher une barre de défilement de taille appropriée.

@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);
}

Enfin, convertissez *ngFor en *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);
}

Au lieu d'itérer sur l'ensemble de la liste, le viewport identifie et parcourt de manière dynamique le sous-ensemble approprié de la liste pour l'utilisateur. Désormais, lorsque l'utilisateur charge la page, le CDK doit afficher le sous-ensemble de la liste qui tient à l'écran (plus un peu de tampon), et tous les événements de défilement dans la fenêtre d'affichage chargeront et restitueront le sous-ensemble approprié de la liste:

Sous-ensembles de rendu CDK d'une liste lorsque l'utilisateur fait défiler la page.

Pour aller plus loin

Les capacités de défilement virtuel du CDK vont beaucoup plus loin que cet exemple de base. Dans l'application exemple, la liste entière était en mémoire, mais elle pouvait être récupérée à la demande pour des applications plus complexes. Pour en savoir plus sur les autres fonctionnalités de ScrollingModule et de la directive cdkVirtualOf, consultez la section Scrolling dans la documentation du CDK.

Image principale par Mr Cup/Fabien Barral sur Unsplash.