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

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

В Element Plus виртуальный скроллинг реализован через компоненты ElVirtualList и опционально с интеграцией в ElTable.


Компонент ElVirtualList

Импорт и базовое использование

import { ElVirtualList } from 'element-plus';

Базовая структура компонента:

<el-virtual-list
  :data="items"
  :item-height="40"
  height="400"
>
  <template #default="{ item, index }">
    <div class="list-item">
      {{ index + 1 }}. {{ item.name }}
    </div>
  </template>
</el-virtual-list>

Пояснения ключевых свойств:

  • data — массив элементов для отображения.
  • item-height — фиксированная высота одного элемента списка (обязательное для корректного расчёта виртуального скролла).
  • height — высота контейнера, определяющая видимую область.

Слот default предоставляет объект с полями item и index для рендеринга каждой видимой строки.


Работа с динамическими размерами элементов

Если высота элементов списка различается, необходимо использовать вычисляемые размеры с помощью свойства estimate-size. Это позволяет компоненту предварительно оценить необходимую высоту элементов, чтобы виртуальный скролл работал корректно.

<el-virtual-list
  :data="items"
  :estimate-size="index => items[index].height"
  height="400"
>
  <template #default="{ item }">
    <div :style="{ height: item.height + 'px' }">
      {{ item.name }}
    </div>
  </template>
</el-virtual-list>

Здесь estimate-size принимает функцию, возвращающую примерную высоту элемента по индексу. Компонент корректно вычисляет смещение для виртуального скролла.


Интеграция с ElTable

Для больших таблиц можно использовать виртуальный скролл совместно с ElTable через обёртку <el-table :data="virtualData" ...> и кастомизацию body через слот:

<el-table
  :data="items"
  style="width: 100%"
  height="400"
  border
>
  <el-table-column prop="name" label="Имя" width="180" />
  <el-table-column prop="age" label="Возраст" width="100" />
</el-table>

Для полноценного виртуального скроллинга в таблицах часто используют сторонние обёртки или компонент ElVirtualList, рендеря строки вручную через слот body.


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

  • Фиксированная высота элементов обеспечивает наилучшую производительность.
  • Минимизация сложных шаблонов в слотах снижает количество перерендерингов.
  • Пагинация данных вместе с виртуальным скроллом помогает управлять большим количеством элементов.
  • Debounce событий скролла предотвращает лишние вызовы обновления виртуального списка.

Программное управление скроллом

ElVirtualList предоставляет методы для программного управления положением скролла:

  • scrollTo(index) — прокручивает список к указанному индексу.
  • scrollToBottom() и scrollToTop() — прокрутка в конец или начало списка.

Пример:

<el-button @click="scrollToItem(50)">Перейти к элементу 51</el-button>

<script>
export default {
  methods: {
    scrollToItem(index) {
      this.$refs.virtualList.scrollTo(index);
    }
  }
}
</script>

<el-virtual-list
  ref="virtualList"
  :data="items"
  :item-height="40"
  height="400"
>
  <template #default="{ item }">
    {{ item.name }}
  </template>
</el-virtual-list>

Реактивность и обновление данных

Компонент полностью поддерживает реактивные массивы Vue. При добавлении или удалении элементов из массива data виртуальный список автоматически пересчитывает позиции:

this.items.push({ name: 'Новый элемент', height: 40 });
this.items.splice(2, 1);

Важно, чтобы изменения массива выполнялись через реактивные методы Vue (push, splice, unshift), иначе компонент не сможет корректно отслеживать обновления.


Пользовательские стили

Элементы списка и контейнер можно стилизовать через CSS:

.list-item {
  padding: 0 16px;
  line-height: 40px;
  border-bottom: 1px solid #ebeef5;
  box-sizing: border-box;
}

Контейнеру можно задать фоновый цвет или тень для визуального отделения виртуального списка:

.el-virtual-list {
  background-color: #fff;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: auto;
}

Итоговые рекомендации

  • Использовать фиксированную высоту элементов для максимальной производительности.
  • Для динамических элементов применять estimate-size.
  • Для таблиц с тысячами строк комбинировать виртуальный список с lazy loading или пагинацией.
  • Минимизировать сложную логику в слотах и обработчиках событий скролла.

Эти приёмы позволяют создавать высокопроизводительные интерфейсы с большими объёмами данных, сохраняя отзывчивость и плавность работы приложения на Vue 3 и Element Plus.