Virtualiza listas grandes con el CDK de Angular

Implementa el desplazamiento virtual para que las listas grandes sean más responsivas.

Stephen Fluin
Stephen Fluin

La lista de desplazamiento es uno de los patrones de IU más comunes en la actualidad, ya sea para explorar un feed de desplazamiento infinito en tu sitio de redes sociales favorito o para navegar por un panel empresarial. Cuando las listas de desplazamiento se vuelven muy largas (cientos, miles o cientos de miles de elementos), el rendimiento de la aplicación puede verse afectado.

Las listas grandes pueden tardar en cargarse porque la aplicación debe cargar y renderizar todos los datos de antemano. También pueden ser lentos para renderizar y navegar , ya que cada elemento de la lista puede tener datos, contenido multimedia y funciones enriquecidos.

Los usuarios pueden tener problemas cuando cargan o se desplazan por la página, lo que genera frustración y abandono de la página.

Desplazamiento virtual en Angular con el kit de desarrollo de componentes

El desplazamiento virtual es la técnica principal que se usa para abordar estos problemas de escala. El desplazamiento virtual da la impresión de una lista muy grande, ya que proporciona una barra de desplazamiento del tamaño adecuado, y la capacidad de navegar por la lista sin que la aplicación tenga que contener toda la lista en la memoria o renderizarla en la página.

En Angular, el kit de desarrollo de componentes (CDK) proporciona el desplazamiento virtual. Si modificas la forma en que iteras por las listas y proporcionas un par de parámetros de configuración adicionales, el desplazamiento virtual del CDK administrará automáticamente la renderización virtual de tus listas, lo que mejorará el rendimiento y la capacidad de respuesta de la página.

En lugar de renderizar toda la lista a la vez, solo se renderizará un subconjunto de los elementos que se ajusten a la pantalla (más un búfer pequeño). A medida que el usuario navega, se calcula y renderiza un nuevo subconjunto de elementos, y se vuelve a usar el DOM existente si se desea.

En el resto de esta publicación, se explica cómo configurar el desplazamiento virtual básico. Puedes ver un ejemplo funcional completo en esta app de ejemplo:

Cómo configurar el desplazamiento virtual

Primero, asegúrate de haber instalado @angular/cdk con tu administrador de paquetes favorito. Para instalarlo con npm, ejecuta este comando en la terminal:

npm install --save @angular/cdk

Agrega ScrollingModule a tu app

Con el CDK instalado, importa ScrollingModule, que controla el desplazamiento virtual, desde el paquete @angular/cdk/scrolling. Luego, agrégalo al array de importaciones de tu módulo:

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

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

Crea un viewport

Para ver cómo funciona el paquete, intenta crear un componente con una lista simple de números del 0 al 99,999:

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

Cuando el navegador renderiza la app, debe renderizar 100,000 elementos <div> individuales. Esto puede estar bien para nodos de texto simples, pero cualquier complejidad en la plantilla repetida no se escalará bien y se multiplicarán significativamente los objetos de escucha de eventos.

Para agregar el desplazamiento virtual y evitar esos problemas, debes crear un viewport uniendo la lista en un elemento <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);
}

Debido a que ScrollingModule renderiza de forma dinámica subconjuntos de la lista, debes especificar la altura del viewport a través de CSS estándar. También debes proporcionarle una sugerencia sobre su contenido a la vista del viewport especificando itemSize. El módulo usa esta información para determinar cuántos elementos se deben conservar en el DOM en un momento determinado y cómo renderizar una barra de desplazamiento del tamaño adecuado.

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

Por último, convierte *ngFor a *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);
}

En lugar de iterar por toda la lista, el viewport identificará e iterará de forma dinámica el subconjunto correcto de la lista para el usuario. Ahora, cuando el usuario cargue la página, el CDK debería renderizar el subconjunto de la lista que se ajusta a la pantalla (más un poco de búfer) y cualquier evento de desplazamiento en el viewport cargará y renderizará el subconjunto adecuado de la lista:

El CDK renderiza subconjuntos de una lista a medida que el usuario se desplaza.

Más información

Las capacidades de desplazamiento virtual de la CDK van mucho más allá de este ejemplo básico. En la app de ejemplo, toda la lista estaba en la memoria, pero se podía recuperar a pedido para aplicaciones más complejas. Para obtener más información sobre las otras funciones de ScrollingModule y la directiva cdkVirtualOf, lee sobre Scrolling en la documentación de CDK.

Imagen hero de Mr Cup / Fabien Barral en Unsplash.