В библиотеке Naive UI компонент
NVirtualList предназначен для эффективного отображения
длинных списков данных. Основная задача виртуализации — рендерить только
видимые элементы, что значительно снижает нагрузку на DOM и повышает
производительность приложений.
Компонент NVirtualList поддерживает как вертикальную,
так и горизонтальную прокрутку, а также динамическую высоту
элементов.
import { createApp } from 'vue';
import { NVirtualList } from 'naive-ui';
const app = createApp({
setup() {
const items = Array.from({ length: 10000 }, (_, i) => `Элемент ${i + 1}`);
return { items };
},
template: `
<n-virtual-list :items="items" :item-size="30" style="height: 400px;">
<template #default="{ item }">
<div>{{ item }}</div>
</template>
</n-virtual-list>
`
});
app.mount('#app');
items — массив данных, которые нужно
отобразить.item-size — высота одного элемента в
пикселях (для вертикального списка) или ширина (для
горизонтального).style — задаёт размеры контейнера для
виртуализации. Без ограниченной высоты или ширины виртуализация работать
не будет.#default — слот для рендеринга каждого
элемента списка.Если высота элементов не фиксирована, можно использовать
:estimated-size, чтобы указать примерную высоту. Это
позволяет виртуальному списку более точно рассчитывать прокрутку.
<n-virtual-list
:items="items"
:estimated-size="50"
style="height: 500px;"
>
<template #default="{ item }">
<div style="padding: 10px; border-bottom: 1px solid #eee;">
{{ item }}
</div>
</template>
</n-virtual-list>
Особенности:
estimated-size позволяет компоненту оптимизировать
рендер, даже если высота элементов различается.Для создания горизонтального виртуального списка необходимо указать
свойство horizontal и задать ширину элемента:
<n-virtual-list
:items="items"
horizontal
:item-size="120"
style="width: 600px; overflow-x: auto; white-space: nowrap;"
>
<template #default="{ item }">
<div style="display: inline-block; width: 120px; text-align: center;">
{{ item }}
</div>
</template>
</n-virtual-list>
Ключевые моменты:
horizontal — активирует горизонтальную
виртуализацию.item-size в данном случае задаёт ширину элемента.white-space: nowrap и overflow-x: auto.Для реализации бесконечной загрузки данных используется событие
onScroll и проверка позиции прокрутки. Например:
<n-virtual-list
:items="items"
:item-size="40"
style="height: 400px;"
@scroll="handleScroll"
>
<template #default="{ item }">
<div>{{ item }}</div>
</template>
</n-virtual-list>
setup() {
const items = ref(Array.from({ length: 100 }, (_, i) => `Элемент ${i + 1}`));
const handleScroll = (e) => {
const { scrollTop, clientHeight, scrollHeight } = e.target;
if (scrollTop + clientHeight >= scrollHeight - 50) {
const nextItems = Array.from({ length: 20 }, (_, i) => `Элемент ${items.value.length + i + 1}`);
items.value.push(...nextItems);
}
};
return { items, handleScroll };
}
Пояснения:
scrollTop + clientHeight >= scrollHeight - 50 позволяет
загружать данные заранее, до достижения конца списка.virtual-scroll-buffer): уменьшает количество
одновременно рендеримых элементов.Можно рендерить полноценные компоненты Vue внутри
NVirtualList, что позволяет использовать сложные элементы с
состоянием:
import { NCard } from 'naive-ui';
<n-virtual-list :items="items" :item-size="100" style="height: 600px;">
<template #default="{ item }">
<n-card title="Карточка">
<p>{{ item.description }}</p>
</n-card>
</template>
</n-virtual-list>
NCard из Naive UI полностью поддерживается.estimated-size.horizontal и правильных
CSS-стилей.scroll.Эти принципы позволяют эффективно использовать виртуальные списки в приложениях на Naive UI, обрабатывая тысячи элементов без тормозов и переполнения DOM.