Виртуализируйте большие списки с помощью Angular CDK

Сделайте большие списки более отзывчивыми, реализовав виртуальную прокрутку.

Стивен Флюин
Stephen Fluin

Прокручиваемый список сегодня является одним из наиболее распространенных шаблонов пользовательского интерфейса, будь то просмотр бесконечно прокручиваемой ленты на вашем любимом сайте социальной сети или навигация по информационной панели предприятия. Когда прокручиваемые списки становятся очень длинными (сотни, тысячи или сотни тысяч элементов), производительность приложения может снизиться.

Большие списки могут загружаться медленно, поскольку приложение должно загружать и отображать все данные заранее. Они также могут медленно рендериться и перемещаться по ним, поскольку каждый элемент в списке может иметь богатые данные, мультимедиа и функциональные возможности.

Пользователи могут испытывать проблемы при загрузке или прокрутке страницы, что приводит к разочарованию и отказу от страницы.

Виртуальная прокрутка в Angular с помощью Component Dev Kit

Виртуальная прокрутка — основной метод, используемый для решения проблем масштабирования. Виртуальная прокрутка создает впечатление очень большого списка (за счет полосы прокрутки соответствующего размера) и дает возможность перемещаться по списку, не требуя от приложения хранить весь список в памяти или отображать его на странице.

В Angular виртуальная прокрутка обеспечивается Component Dev Kit (CDK) . Изменив способ перебора списков и предоставив пару дополнительных параметров конфигурации, виртуальная прокрутка CDK будет автоматически управлять виртуальным рендерингом ваших списков, улучшая производительность страницы и скорость реагирования.

Вместо того, чтобы отображать весь список за раз, будет отображаться только подмножество элементов, которое помещается на экране (плюс небольшой буфер). По мере навигации пользователя рассчитывается и отображается новое подмножество элементов, при необходимости повторно используя существующую модель DOM.

В оставшейся части статьи рассказывается, как настроить базовую виртуальную прокрутку. Полный рабочий пример можно увидеть в этом примере приложения:

Настройка виртуальной прокрутки

Сначала убедитесь, что вы установили @angular/cdk используя свой любимый менеджер пакетов. Чтобы установить его с помощью npm, выполните в терминале следующую команду:

npm install --save @angular/cdk

Добавьте ScrollingModule в свое приложение

Установив CDK, импортируйте ScrollingModule , который обрабатывает виртуальную прокрутку, из пакета @angular/cdk/scrolling . Затем добавьте его в массив импорта вашего модуля:

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

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

Создать область просмотра

Чтобы увидеть, как работает пакет, попробуйте создать компонент с простым списком чисел от 0 до 99 999:

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

Когда браузер отображает приложение, он должен отобразить 100 000 отдельных элементов <div> . Это может быть хорошо для простых текстовых узлов, но любая сложность повторяющегося шаблона не будет хорошо масштабироваться, и количество прослушивателей событий будет значительно увеличено.

Чтобы добавить виртуальную прокрутку и избежать этих проблем, вам необходимо создать область просмотра, обернув список элементом <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);
}

Поскольку ScrollingModule динамически отображает подмножества списка, вам необходимо указать высоту области просмотра с помощью стандартного CSS. Вам также необходимо дать окну просмотра подсказку о его содержимом, указав itemSize . Модуль использует эту информацию, чтобы определить, сколько элементов следует хранить в DOM в данный момент и как визуализировать полосу прокрутки соответствующего размера.

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

Наконец, преобразуйте *ngFor в *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);
}

Вместо перебора всего списка область просмотра будет динамически идентифицировать и перебирать правильное для пользователя подмножество списка. Теперь, когда пользователь загружает страницу, CDK должен отображать подмножество списка, которое помещается на экране (плюс немного буфера), и любые события прокрутки в области просмотра будут загружать и отображать соответствующее подмножество списка:

CDK отображает подмножества списка при прокрутке пользователем.

Идем дальше

Возможности виртуальной прокрутки CDK выходят далеко за рамки этого базового примера. В примере приложения весь список находился в памяти, но для более сложных приложений его можно было получить по требованию. Подробнее о других возможностях ScrollingModule и директиве cdkVirtualOf можно узнать, прочитав о Scrolling в документации CDK .

Изображение героя от Mr Cup/Fabien Barral на Unsplash .