Skip to content

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() 进行深度选择,以确保样式生效。