Виртуализация больших списков необходима для оптимизации производительности веб-приложений при работе с массивами данных, состоящими из тысяч элементов. Naive UI предоставляет встроенные решения для виртуализации через компонент n-virtual-list, который эффективно рендерит только видимую часть элементов, сокращая нагрузку на DOM и ускоряя отрисовку.
Компонент n-virtual-list основан на принципе “windowing”: он создает контейнер фиксированной высоты и отображает только те элементы, которые находятся в пределах видимой области. Все остальные элементы остаются в виртуальном пространстве, не создавая лишних узлов в DOM.
Простейший пример использования n-virtual-list выглядит так:
<template>
<n-virtual-list
:items="items"
:item-height="50"
height="400"
>
<template #default="{ item }">
<div class="list-item">{{ item.text }}</div>
</template>
</n-virtual-list>
</template>
<script setup>
import { ref } from 'vue'
const items = ref(
Array.from({ length: 10000 }, (_, i) => ({ text: `Элемент ${i + 1}` }))
)
</script>
<style>
.list-item {
display: flex;
align-items: center;
height: 50px;
padding: 0 10px;
border-bottom: 1px solid #eee;
}
</style>
Ключевые моменты:
items — массив данных для отображения. Каждый элемент
должен быть уникальным, особенно при динамическом обновлении.item-height — фиксированная высота каждого элемента
списка. Если элементы имеют разную высоту, необходимо использовать режим
динамической виртуализации.height — высота контейнера списка, определяющая область
видимости.Если элементы списка имеют разную высоту, Naive UI позволяет использовать dynamic-height. Для этого нужно передавать функцию, которая возвращает высоту каждого элемента:
<n-virtual-list
:items="items"
:item-height="getItemHeight"
height="400"
>
<template #default="{ item }">
<div>{{ item.text }}</div>
</template>
</n-virtual-list>
<script setup>
const getItemHeight = (item) => item.height || 50
const items = ref(
Array.from({ length: 5000 }, (_, i) => ({
text: `Элемент ${i + 1}`,
height: Math.floor(Math.random() * 50) + 50
}))
)
</script>
Использование функции для высоты позволяет компоненту корректно рассчитывать виртуальную область, предотвращая визуальные “прыжки” при скролле.
Компонент поддерживает реактивное обновление массива и интеграцию с подгрузкой данных по мере прокрутки. Основной подход:
@scroll событие для отслеживания текущей
позиции.items.Пример:
<n-virtual-list
:items="items"
:item-height="50"
height="400"
@scroll="handleScroll"
>
<template #default="{ item }">
<div>{{ item.text }}</div>
</template>
</n-virtual-list>
<script setup>
const items = ref(
Array.from({ length: 100, }, (_, i) => ({ text: `Элемент ${i + 1}` }))
)
const handleScroll = (e) => {
const { scrollTop, clientHeight, scrollHeight } = e.target
if (scrollTop + clientHeight >= scrollHeight - 100) {
const nextItems = Array.from({ length: 50 }, (_, i) => ({
text: `Элемент ${items.value.length + i + 1}`
}))
items.value.push(...nextItems)
}
}
</script>
Особенности:
Для больших массивов важно использовать ключи
элементов через :key, чтобы Vue корректно
отслеживал изменения:
<template #default="{ item, index }">
<div :key="index">{{ item.text }}</div>
</template>
Дополнительно можно комбинировать виртуализацию с debounce скролл-событий, чтобы снизить нагрузку на обработчики событий при быстром скролле.
Компонент позволяет полностью контролировать стили:
item-height, CSS
padding и margin).overflow-y.n-virtual-list может принимать
кастомные классы для интеграции с темами.Пример кастомного оформления:
.n-virtual-list {
border: 1px solid #ccc;
border-radius: 6px;
background-color: #fafafa;
}
.list-item {
border-bottom: 1px solid #eee;
transition: background 0.2s;
}
.list-item:hover {
background-color: #f0f0f0;
}
При рендеринге 10 000 элементов обычный <div>
список вызывает сильные задержки и возможные падения браузера.
Виртуализация через n-virtual-list:
header и
footer для вставки фиксированных элементов
списка.В сочетании с Vue 3 и Composition API, Naive UI позволяет создавать масштабируемые интерфейсы со списками от нескольких сотен до десятков тысяч элементов без снижения отзывчивости.