Виртуальный скролл

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

Пример
Исходный код

Документация API Спецификация Axure

Базовая конфигурация

Для корректной работы виртуального скролла в списке, необходимо использовать платформенный контейнер для прокрутки контента Controls/scroll:Container.

<!-- WML -->
<Controls.scroll:Container>
   <Controls.list:View source="{{_viewSource}}"/>
</Controls.scroll:Container>

Поскольку скролл-контейнер работает как нативный скролл, для корректной работы обязательно требуется ограничить его по высоте, например, задав стиль height: 100% или height: 500px.

<!-- WML -->
<Controls.scroll:Container attr:style="height: 500px;">
   <Controls.list:View source="{{_viewSource}}"/>
</Controls.scroll:Container>

Оптимизация производительности виртуального скроллинга

Для оптимизации производительности виртуального скролла необходимо задать virtualScrollConfig.

Установить количество отображаемых элементов при инициализации списка позволяет свойство pageSize. Чем меньше элементов в pageSize, тем быстрее будет происходить отрисовка списка, но следует учитывать предполагаемую высоту строк, поскольку область виртуального скролла может получится меньше высоты скролл-контейнера.

Оптимальным для pageSize является значение, примерно равное количеству элементов, помещающихся на 2-3 страницы отображаемой области. Если значение опции будет меньше, то одновременно будет перерисовываться меньшее число элементов, но сдвиги диапазона виртуального скролла будут происходить чаще. А при слишком маленьком значении список будет обновляться очень часто. Для более точного определения оптимального значения опции pageSize можно воспользоваться профилированием (вкладка "performance" в консоли), сравнив производительность при нескольких разных значениях опции.

<!-- WML -->
<Controls.scroll:Container>
   <Controls.list:View source="{{_viewSource}}">
       <ws:virtualScrollConfig pageSize="{{100}}"/>
   </Controls.list:View>
</Controls.scroll:Container>

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

<!-- WML -->
<Controls.scroll:Container>
   <Controls.list:View>
      <ws:virtualScrollConfig pageSize="{{40}}" segmentSize="{{10}}"/>
   </Controls.list:View>
</Controls.scroll:Container>

В ряде случаев, когда высоты элементов известны заранее, имеется возможность получить их из источника данных. Для этого нужно установить значение для опции itemHeightProperty — имя поля, которое содержит высоту элемента.

<!-- WML -->
<Controls.scroll:Container>
   <Controls.list:View>
      <ws:virtualScrollConfig pageSize="{{40}}" itemHeightProperty="itemHeight"/>
   </Controls.list:View>
</Controls.scroll:Container>

В случае, когда известна высота контейнера со списком, её можно передать в опцию viewportHeight. В совокупности с itemHeightProperty это позволит быстро рассчитать количество изначально отображаемых элементов без доступа к реальному DOM. Также эта оптимизация может быть использована при построении на сервере.

<!-- WML -->
<Controls.scroll:Container>
   <Controls.list:View>
      <ws:virtualScrollConfig pageSize="{{40}}" itemHeightProperty="itemHeight" viewportHeight="{{500}}"/>
   </Controls.list:View>
</Controls.scroll:Container>

Существует возможность выбрать режим управления элементами виртуальным скроллом. Для этого используется опция mode, в которой доступно два режима:

  • remove (используется по умолчанию) ― режим, в котором элементы вне отображаемого диапазона удаляются из DOM. Данный режим используется в большинстве случаев, когда шаблон элемента относительно "дёшево" перерисовать.
  • hide ― режим, в котором элементы вне отображаемого диапазона скрываются из DOM с помощью display: none. Данный режим необходимо использовать в случаях, когда шаблон элемента "тяжёлый", и его перерисовка занимает продолжительное время.
<!-- WML -->
<Controls.scroll:Container>
   <Controls.list:View>
      <ws:virtualScrollConfig pageSize="{{40}}" mode="remove"/>
   </Controls.list:View>
</Controls.scroll:Container>

Поддержка виртуальной прокрутки при наличии дополнительных контролов в скролл-контейнере

Зачастую, в скролл-контейнере над или под списком располагаются дополнительные контролы. При виртуальной прокрутке эти контролы должны "вытесняться" точно также, как и элементы самого списка.

Для решения этой задачи дополнительные контролы необходимо обернуть в специальный контейнер Controls/scroll:VirtualScrollContainer:

<!-- WML -->
<Controls.scroll:Container>
   <Controls.scroll:VirtualScrollContainer>
      <Controls.buttons:Button 
          viewMode="link" 
          caption="Контент, расположенный над списком"/>
   </Controls.scroll:VirtualScrollContainer>
   <Controls.list:View 
      source="{{_viewSource}}" 
      navigation="{{_navigation}}">
      <ws:virtualScrollConfig pageSize="{{100}}"/>
   </Controls.list:View>
</Controls.scroll:Container>

Таким образом, как только элементы списка заполнят экран, дополнительные контролы будут убраны из верстки, и всё место скролл-контейнера будет отведено для отображения списка.