Skip to content
API 风格:

VirtualList 虚拟列表 ​

只渲染可视窗口内的项,支持定高与动态高度两种模式(动态模式按预计算偏移 + 二分查找定位)。

定高 ​

定高
第 0 项 · 项目 1
第 1 项 · 项目 2
第 2 项 · 项目 3
第 3 项 · 项目 4
vue
<script setup lang="ts">
const listData = Array.from({ length: 1000 }, (_, i) => `项目 ${i + 1}`)
</script>

<template>
  <LhVirtualList :data="listData" :height="200" :item-height="40">
    <template #default="{ item, index }">
      <div>第 {{ index }} 项 · {{ item }}</div>
    </template>
  </LhVirtualList>
</template>
vue
<script>
export default {
  data() {
    return {
      listData: Array.from({ length: 1000 }, (_, i) => `项目 ${i + 1}`),
    }
  },
}
</script>

<template>
  <LhVirtualList :data="listData" :height="200" :item-height="40">
    <template #default="{ item, index }">
      <div>第 {{ index }} 项 · {{ item }}</div>
    </template>
  </LhVirtualList>
</template>

动态高度 ​

itemSize 返回每项高度(可基于测量结果动态返回)。

动态高度
项目 1
项目 2
项目 3
vue
<script setup>
const dynamicSize = (index) => (index % 3 === 0 ? 56 : 36)
</script>

<template>
  <LhVirtualList :data="listData" :height="200" :item-size="dynamicSize">
    <template #default="{ item, index }">{{ item }}</template>
  </LhVirtualList>
</template>
vue
<script>
export default {
  data() {
    return {
      listData: Array.from({ length: 1000 }, (_, i) => `项目 ${i + 1}`),
    }
  },
  methods: {
    dynamicSize(index) {
      return index % 3 === 0 ? 56 : 36
    },
  },
}
</script>

<template>
  <LhVirtualList :data="listData" :height="200" :item-size="dynamicSize">
    <template #default="{ item, index }">{{ item }}</template>
  </LhVirtualList>
</template>

预渲染缓冲 ​

overscan 指定可视窗口外上下各预渲染多少行,减少快速滚动时的白屏。

overscan
第 0 项 · 项目 1
第 1 项 · 项目 2
第 2 项 · 项目 3
第 3 项 · 项目 4
第 4 项 · 项目 5
第 5 项 · 项目 6
第 6 项 · 项目 7
第 7 项 · 项目 8
第 8 项 · 项目 9
第 9 项 · 项目 10
第 10 项 · 项目 11
第 11 项 · 项目 12
第 12 项 · 项目 13
第 13 项 · 项目 14
第 14 项 · 项目 15
第 15 项 · 项目 16
vue
<script setup lang="ts">
const listData = Array.from({ length: 1000 }, (_, i) => `项目 ${i + 1}`)
</script>

<template>
  <LhVirtualList
    :data="listData"
    :item-height="40"
    :height="200"
    :overscan="8"
  />
</template>
vue
<script>
export default {
  data() {
    return {
      listData: Array.from({ length: 1000 }, (_, i) => `项目 ${i + 1}`),
    }
  },
}
</script>

<template>
  <LhVirtualList
    :data="listData"
    :item-height="40"
    :height="200"
    :overscan="8"
  />
</template>

API ​

LhVirtualList Props ​

属性名说明类型默认值
data数据源(项渲染由 default 插槽负责)any[]—
height容器高度(数字为 px)string | number—
itemHeight定高模式的项高number—
itemSize动态高度模式:由调用方返回每项高度(index: number) => number—
overscan过扫描项数numberLH_VIRTUAL_OVERSCAN
sxsx 快速布局属性LhSxProps—

插槽:default(作用域 { item, index })。

无障碍 ​

  • 容器 overflow: auto 可键盘滚动;窗口外的项不在 DOM 中,屏读按需获取(长列表的固有取舍,建议配合搜索/筛选缩小范围)
  • 若需完整语义表格请用 Table(其虚拟滚动同样由 core 纯函数驱动)

类型定义 ​

本组件对外导出的 TypeScript 类型结构如下(自动提取自 packages/components/virtual-list/src/types.ts 与 @lh-ui/share/core/* 源码,点击各条目展开查看完整定义;属性说明见上方 Props 表):

LhVirtualListProps
ts
export interface LhVirtualListProps {
  /** 数据源(项渲染由 default 插槽负责) */
  data: any[]
  /** 容器高度(数字为 px) */
  height: number | string
  /** 定高模式的项高(与 itemSize 二选一;提供了 itemSize 时走动态高度) */
  itemHeight?: number
  /** 动态高度模式:由调用方返回每项高度 */
  itemSize?: (index: number) => number
  /** 过扫描项数 */
  overscan?: number
  /** sx 快速布局属性 */
  sx?: LhSxProps
}

常量 ​

本组件用到的公开常量如下(可在 Props 表的「类型 / 默认值」列点击同名条目跳转至此):

LH_VIRTUAL_ITEM_SIZE (来自 @lh-ui/share/core/virtual-list)
ts
/** 默认估算项高 */
export const LH_VIRTUAL_ITEM_SIZE = 40