与 Semi Design 的技术差异:Semi 没有独立的 VirtualList 组件,它的虚拟滚动能力由第三方库
react-window(Tree / TreeSelect / Cascader / Select)与react-virtualized(List 无限长列表)提供,作为内部实现细节,不对外导出。Svelte 生态没有可直接复用的等价库,因此本库自建了这个 headlessVirtualList基座,被 Table / List / TreeSelect / Cascader 等组件复用。它是技术栈差异导致的必要自建,Semi 官网无对应文档页。
代码演示
如何引入
import { VirtualList } from '@chenzy-design/svelte'; 基础虚拟列表
通过 data 传入数据、itemSize 指定固定行高,万行数据仅渲染视口内的可见行。
固定行高(1 万行,itemSize=36,仅渲染视口内行)
第 1 行
第 2 行
第 3 行
第 4 行
第 5 行
第 6 行
第 7 行
第 8 行
第 9 行
动态/不定高
itemSize='auto' 时用 ResizeObserver 实测每行真实高度并修正偏移,estimatedItemSize 提供首屏占位估算。
动态/不定高(itemSize='auto',估算 56px,实测后修正偏移)
第 1 条 — 虚拟列表只渲
第 2 条 — 虚拟列表只渲染
第 3 条 — 虚拟列表只渲染视
第 4 条 — 虚拟列表只渲染视口
第 5 条 — 虚拟列表只渲染视口内
第 6 条 — 虚拟列表只渲染视口内的
第 7 条 — 虚拟列表只渲染视口内的行
第 8 条 — 虚拟列表只渲染视口内的行,
滚动到指定项
通过 bind:this 拿到组件实例,命令式调用 scrollToIndex(index, { align }) 滚动到指定行。
#0 — 第 1 行
#1 — 第 2 行
#2 — 第 3 行
#3 — 第 4 行
#4 — 第 5 行
#5 — 第 6 行
#6 — 第 7 行
#7 — 第 8 行
#8 — 第 9 行
横向虚拟化
horizontal 沿 x 轴排列,itemSize 作列宽(仅支持 fixed 定宽)。
横向虚拟化(horizontal,列宽 80px,1 万列只渲染视口列)
1
2
3
自定义项渲染
renderItem 内可组合任意富结构(Tag、图标等),只要保证行高与 itemSize 一致。
自定义项渲染(renderItem 内组合 Tag + 富结构,固定行高 52px) 任务 1 已完成 任务 2 进行中 任务 3 进行中 任务 4 进行中 任务 5 已完成 任务 6 进行中 任务 7 进行中 任务 8 进行中
P0
P1
P2
P0
P1
P2
P0
P1
API 参考
VirtualList
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| class | 根节点自定义类名 | string | - |
| data | 列表数据源 | T[] | [] |
| estimatedItemSize | 动态模式(itemSize=‘auto’)下的初始估算行高(px),用于首屏占位与总高估算 | number | 40 |
| getKey | 每项的稳定 key 生成函数 | (item: T, index: number) => string | number | (_, index) => index |
| height | 视口主轴尺寸(vertical 为高度、horizontal 为宽度);数字按 px,字符串用 ResizeObserver 测量 | number | string | 400 |
| horizontal | 横向虚拟化:沿 x 轴排列、读/写 scrollLeft | boolean | false |
| itemSize | 固定行高/列宽(px);传 auto 启用动态不定高测量(horizontal 暂不支持 dynamic) | number | auto | 40 |
| overscan | 视口上下额外预渲染的行数 | number | 3 |
| renderItem | 渲染每一项的模板 | Snippet<[item, index]> | - |
| scrollTarget | 滚动源:self 内部容器自身滚动 / window 用窗口滚动(适合整页长列表,仅 vertical) | self | window | self |
方法
通过 bind:this 拿到组件实例后可命令式调用:
| 方法 | 说明 |
|---|---|
| scrollToIndex(index, options?) | 滚动到指定项;options.align 支持 start / center / end |
无障碍
- VirtualList 本身是透明容器,不添加额外 role;具体 role(
list/grid/listbox等)由上层调用方传入,确保语义由业务层决定。 - 每行渲染时注入
aria-setsize(数据总量)和aria-posinset(当前行在全列表中的位置),使屏幕阅读器可感知「第 N 条,共 M 条」。 - 当前聚焦的行不会被虚拟回收,确保键盘导航时焦点不丢失。
- 滚动时以 rAF 节流控制 ARIA 属性更新频率,避免辅助技术被频繁的属性变更淹没。
设计变量
变量 | 默认值 | 用法 |
|---|---|---|
| --cd-virtual-list-bg | var(--cd-color-bg-0) | 虚拟列表容器背景色 |
| --cd-virtual-list-scrollbar | var(--cd-color-fill-1) | 虚拟列表滚动条颜色 |
显示第 1 条-第 2 条,共 2 条
- 1