v-virtual-list 指令
介绍
v-virtual-list
指令用于实现高性能的虚拟滚动列表,特别适合渲染大数据量场景。通过动态计算可视区域、自动测量元素高度、精准定位渲染范围,实现流畅的万级数据滚动体验。
使用方法
通过配置 data 属性,可以设置待展示的完整数据集;containerHeight 属性用于定义可视区域的高度,并可根据需求灵活调整;renderItem 属性则支持自定义渲染逻辑,使数据的展示结构和样式更加个性化。
vue
<template>
<div
v-virtual-list="{
data: countAndColorsItems,
containerHeight: 600,
renderItem: renderCountAndColorsItem
}"
class="count-and-colors-list"
></div>
</template>
查看代码
vue
<template>
<div
v-virtual-list="{
data: countAndColorsItems,
containerHeight: 300,
renderItem: renderCountAndColorsItem
}"
class="count-and-colors-list"
></div>
</template>
<script setup lang="ts">
import { ref, h } from 'vue'
import { vVirtualList } from '@cp-vuedir/core'
interface CountAndColorsItem {
id: number
title: string
content: string
}
const countAndColorsItems = ref<CountAndColorsItem[]>(
Array.from({ length: 100000 }, (_, i) => ({
id: i + 1,
title: `Item ${i + 1}`,
content: 'Content with color'
}))
)
const renderCountAndColorsItem = (item: CountAndColorsItem) =>
h(
'div',
{
class: 'count-and-colors-item',
key: item.id
},
[h('p', item.title), h('p', item.content)]
)
</script>
<style scoped>
.count-and-colors-list {
width: 100%;
margin: 20px auto;
border: 1px solid #e0e0e0;
}
:deep(.count-and-colors-item) {
display: flex;
justify-content: space-between;
padding: 6px;
border-bottom: 1px solid #eee;
box-sizing: border-box;
}
/* 滚动条 */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-thumb {
background: #888;
border-radius: 10px;
}
</style>
支持自定义数据的展示结构
查看代码
vue
<template>
<div
v-virtual-list="{
data: complexItems,
containerHeight: 300,
renderItem: renderComplexItem
}"
class="count-and-colors-list"
></div>
</template>
<script setup lang="ts">
import { ref, h } from 'vue'
import { vVirtualList } from '@cp-vuedir/core'
interface ComplexItem {
id: number
name: string
sku: string
price: string
stock: number
description: string
}
const complexItems = ref<ComplexItem[]>(
Array.from({ length: 10000 }, (_, i) => ({
id: i + 1,
name: `Product ${i + 1}`,
sku: `SKU-${Math.random().toString(36).slice(2, 10)}`,
price: (Math.random() * 1000).toFixed(2),
stock: Math.floor(Math.random() * 1000),
description: 'Detailed product description with multiple lines of text'
}))
)
const renderComplexItem = (item: ComplexItem) =>
h(
'div',
{
class: 'complex-item',
key: item.id
},
[h('p', item.name), h('p', item.sku), h('p', item.price), h('p', item.stock), h('p', item.description)]
)
</script>
<style scoped>
.count-and-colors-list {
width: 100%;
margin: 20px auto;
border: 1px solid #e0e0e0;
}
:deep(.complex-item) {
display: flex;
justify-content: space-between;
padding: 6px;
border-bottom: 1px solid #eee;
box-sizing: border-box;
}
/* 滚动条 */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-thumb {
background: #888;
border-radius: 10px;
}
</style>
支持动态高度
查看代码
vue
<template>
<div
v-virtual-list="{
data: dynamicItems,
containerHeight: 300,
renderItem: renderComplexItem
}"
class="count-and-colors-list"
></div>
</template>
<script setup lang="ts">
import { ref, h } from 'vue'
import { vVirtualList } from '@cp-vuedir/core'
interface DynamicItem {
id: number
title: string
content: string
}
const dynamicItems = ref<DynamicItem[]>(
Array.from({ length: 10000 }, (_, i) => {
const lines = Math.floor(Math.random() * 10) + 1 // 1-10 行
return {
id: i + 1,
title: `Document ${i + 1}`,
content: Array(lines).fill('This is dynamic content.').join(' ')
}
})
)
const renderComplexItem = (item: DynamicItem) => {
return h('div', { class: 'complex-item', key: item.id }, [h('span', item.title), h('span', item.content)])
}
</script>
<style scoped>
.count-and-colors-list {
width: 100%;
margin: 20px auto;
border: 1px solid #e0e0e0;
overflow-y: auto; /* 启用滚动 */
max-height: 300px;
}
:deep(.complex-item) {
display: flex;
flex-direction: column;
padding: 6px;
border-bottom: 1px solid #eee;
box-sizing: border-box;
}
/* 滚动条美化 */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-thumb {
background: #888;
border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
</style>
API
属性名 | 说明 | 类型 | 是否必选 | 默认值 |
---|---|---|---|---|
data | 需要渲染的完整数据集 | T[] | () => [] | |
containerHeight | 虚拟列表容器的可视区域高度(单位:px) | number | 300 | |
renderItem | 自定义渲染每一项的函数,返回 VNode | (item: any, index: number) => VNode | - |
注意事项
注意事项
注意浏览器兼容
- 若需修改渲染函数中的样式,请使用 :deep() 进行深度选择,以确保样式生效。