Источник: Nuances of Programming
1. Виртуальная прокрутка
Виртуальная прокрутка — наиболее эффективный способ обработки больших списков. Благодаря Angular CDK и другим плагинам ее можно с легкостью реализовать в любом компоненте.
Концепция проста:
- элемент отображается только в том случае, если он находится в пределах видимых границ контейнера.
Чтобы использовать модуль прокрутки CDK, для начала нужно его установить:
npm i @angular/cdk
Затем импортируем модуль:
Теперь виртуальную прокрутку можно использовать в компонентах:
Несмотря на простоту реализации, результаты впечатляют. Компонент с легкостью отображает тысячи элементов.
Если виртуальная прокрутка настолько хороша и проста в реализации, то зачем использовать другие методы? На это есть несколько причин:
- Результат сильно зависит от реализации: трудно управлять всеми возможными сценариями с помощью одной единственной реализации. Чем сложнее элемент, тем сложнее предсказать результат.
- Модуль — это еще один большой кусок кода, добавленный в приложение.
- Доступность и практичность: скрытые элементы не отображаются и, следовательно, не доступны для поиска.
Виртуальная прокрутка — отличный вариант (если она работает) при наличии:
- неопределенного и, возможно, огромного списка элементов (предположительно больше 5 Кб, однако зависит от сложности каждого элемента);
- бесконечной прокрутки элементов.
2. Ручной рендеринг
Один из вариантов ускорения рендеринга большого списка элементов — это ручной рендеринг с использованием API Angular, вместо *ngFor.
Возьмем простой шаблон цикла ngFor:
Для расчета рендеринга 10000 простых элементов мы будем использовать бенчмарк, вдохновленный js-frameworks-benchmark.
Первый тест выполнен с помощью *ngFor. Результаты: на скриптинг потребовалось 1099 мс, на рендеринг — 1553 мс, а на покрас — 3 мс.
С помощью API Angular эти элементы можно визуализировать вручную.
Код контроллера изменяется следующим образом:
- объявляем шаблон и контейнер
@ViewChild('itemsContainer', { read: ViewContainerRef }) container: ViewContainerRef;
@ViewChild('item', { read: TemplateRef }) template: TemplateRef<any>;
- после создания данных визуализируем их с помощью метода ViewContainerRef createEmbeddedViewwhen:
Результаты показывают небольшое улучшение:
- Скриптинг — 734 мс, рендеринг — 1443 мс и покрас — 2 мс:
Тем не менее на практике этот процесс все еще недостаточно быстрый, поскольку при нажатии кнопки браузер зависает на несколько секунд.
Процесс выглядит следующим образом (движения мышь имитируют индикатор загрузки 😅):
Теперь перейдем к прогрессивному рендерингу в сочетании с ручным.
3. Прогрессивный рендеринг
Концепция прогрессивного рендеринга заключается в том, чтобы визуализировать поднабор элементов и отложить рендеринг других элементов в цикле событий, что позволяет браузеру плавно и последовательно отображать все элементы.
Код очень простой:
- мы создаем интервал каждые 10 мс и отображаем 500 элементов одновременно;
- когда все элементы будут отображены согласно индексу, мы останавливаем интервал и прерываем цикл.
Обратите внимание, что количество отображаемых элементов и время интервала полностью зависят от конкретного случая. Например, при наличии большого количества сложных элементов рендеринг 500 из них будет очень медленным.
Как видите, статистика выглядит хуже:
Однако увеличение времени рендеринга остается незаметным для пользователя, поскольку 500 элементов отображаются одновременно, а сам процесс происходит за пределами контейнера.
При изменении размера контейнера или положения прокрутки в некоторых случаях могут возникнуть проблемы, которые необходимо устранить.
Процесс выглядит следующим образом:
Заключение
Вышеуказанные методы будут полезны, если виртуальная прокрутка оказывается не лучшим вариантом.
Однако во многих случаях виртуальная прокрутка с использованием такой великолепной библиотеки, как Angular CDK, является лучшим способом работы с большими списками.
Читайте также:
Читайте нас в телеграмме и vk
Перевод статьи Giancarlo Buomprisco: 3 Ways to Render Large Lists in Angular