Virtualizar listas grandes com o CDK do Angular

Implemente a rolagem virtual para tornar listas grandes mais responsivas.

Stephen Fluin
Stephen Fluin

A lista de rolagem é um dos padrões de interface mais comuns atualmente, seja para navegar em um feed de rolagem infinita no seu site de mídia social favorito ou para navegar em um painel corporativo. Quando as listas de rolagem ficam muito longas (centenas, milhares ou centenas de milhares de itens), o desempenho do aplicativo pode ser afetado.

Listas grandes podem ser lentas para carregar porque o aplicativo precisa carregar e renderizar todos os dados de uma vez. A renderização e a navegação também podem ser lentas , porque cada item da lista pode ter dados, mídia e funcionalidades avançados.

Os usuários podem ter problemas ao carregar ou rolar a página, o que leva à frustração e ao abandono da página.

Rolagem virtual no Angular com o Component Dev Kit

A rolagem virtual é a principal técnica usada para resolver esses problemas de escala. A rolagem virtual dá a impressão de uma lista muito grande, fornecendo uma barra de rolagem de tamanho adequado, e a capacidade de navegar pela lista sem exigir que o aplicativo mantenha a lista inteira na memória ou a renderize na página.

No Angular, a rolagem virtual é fornecida pelo Component Dev Kit (CDK). Ao modificar a forma como você itera listas e fornecer alguns parâmetros de configuração adicionais, a rolagem virtual do CDK vai gerenciar automaticamente a renderização virtual das listas, melhorando a performance e a capacidade de resposta da página.

Em vez de renderizar a lista inteira de uma vez, apenas um subconjunto dos itens que cabem na tela (mais um pequeno buffer) será renderizado. À medida que o usuário navega, um novo subconjunto de itens é calculado e renderizado, reutilizando o DOM atual, se necessário.

O restante desta postagem explica como configurar a rolagem virtual básica. Confira um exemplo completo e funcional neste app de exemplo:

Como configurar a rolagem virtual

Primeiro, verifique se você instalou o @angular/cdk usando seu gerenciador de pacotes favorito. Para instalar usando o npm, execute este comando no terminal:

npm install --save @angular/cdk

Adicionar ScrollingModule ao app

Com o CDK instalado, importe ScrollingModule, que processa a rolagem virtual, do pacote @angular/cdk/scrolling. Em seguida, adicione-o à matriz de importações do módulo:

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

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

Criar uma janela de visualização

Para saber como o pacote funciona, crie um componente com uma lista simples de números de 0 a 99.999:

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

Quando o navegador renderiza o app, ele precisa renderizar 100.000 elementos <div> individuais. Isso pode ser adequado para nós de texto simples, mas qualquer complexidade no modelo repetido não será dimensionado corretamente, e os listeners de eventos serão multiplicados significativamente.

Para adicionar a rolagem virtual e evitar esses problemas, é necessário criar uma viewport envolvendo a lista em um 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);
}

Como o ScrollingModule renderiza dinamicamente subconjuntos da lista, é necessário especificar a altura da viewport usando o CSS padrão. Você também precisa dar uma dica à viewport sobre o conteúdo dela especificando o itemSize. O módulo usa essas informações para determinar quantos itens manter no DOM em um determinado momento e como renderizar uma barra de rolagem de tamanho adequado.

@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 fim, converta *ngFor em *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);
}

Em vez de iterar pela lista inteira, a viewport vai identificar e iterar dinamicamente o subconjunto correto da lista para o usuário. Agora, quando o usuário carrega a página, o CDK renderiza o subconjunto da lista que cabe na tela (mais um pouco de buffer), e todos os eventos de rolagem na viewport carregam e renderizam o subconjunto apropriado da lista:

O CDK renderiza subconjuntos de uma lista à medida que o usuário rola.

Mais informações

As habilidades de rolagem virtual do CDK vão muito além desse exemplo básico. No app de exemplo, a lista inteira estava na memória, mas podia ser buscada sob demanda para aplicativos mais complexos. Saiba mais sobre os outros recursos de ScrollingModule e a diretiva cdkVirtualOf lendo sobre Scrolling na documentação do CDK.

Imagem principal de Mr Cup / Fabien Barral no Unsplash.