VirtualList 虚拟列表
只渲染可见行 + overscan 的虚拟列表,支持固定 / 变高行;十万行无掉帧。
English translation pending This page hasn't been translated yet — falling back to Chinese. PRs welcome on GitHub.
基础用法
itemHeight 接受 number(固定高)或 (item, index) => number(变高)。固定高场景几乎零开销(O(1) 计算窗口);变高场景线性遍历,约 10k 行内无感知。
背景 视口
Row #1Lorem ipsum dolor sit amet — 0
Row #2Lorem ipsum dolor sit amet — 7
Row #3Lorem ipsum dolor sit amet — 14
Row #4Lorem ipsum dolor sit amet — 21
Row #5Lorem ipsum dolor sit amet — 28
Row #6Lorem ipsum dolor sit amet — 35
Row #7Lorem ipsum dolor sit amet — 42
Row #8Lorem ipsum dolor sit amet — 49
Row #9Lorem ipsum dolor sit amet — 56
Row #10Lorem ipsum dolor sit amet — 63
Row #11Lorem ipsum dolor sit amet — 70
Row #12Lorem ipsum dolor sit amet — 77
Row #13Lorem ipsum dolor sit amet — 84
Row #14Lorem ipsum dolor sit amet — 91
<script setup lang="ts">
import { CfVirtualList } from '@chufix-design/vue';
const items = Array.from({ length: 50_000 }, (_, i) => ({
id: i,
title: `Row #${i + 1}`,
desc: `Lorem ipsum dolor sit amet — ${(i * 7) % 1000}`,
}));
</script>
<template>
<CfVirtualList
:items="items"
:item-height="48"
:height="320"
:item-key="(it) => it.id"
>
<template #default="{ item }">
<div class="demo-row">
<strong>{{ item.title }}</strong>
<span class="demo-row__sub">{{ item.desc }}</span>
</div>
</template>
</CfVirtualList>
</template>
<style scoped>
.demo-row { padding: 8px 12px; border-bottom: 1px solid var(--line-1); display: flex; flex-direction: column; }
.demo-row__sub { color: var(--fg-3); font-size: var(--t-11); }
</style> <script setup>
import { CfVirtualList } from '@chufix-design/vue';
const items = Array.from({ length: 50_000 }, (_, i) => ({
id: i,
title: `Row #${i + 1}`,
desc: `Lorem ipsum dolor sit amet — ${(i * 7) % 1000}`,
}));
</script>
<template>
<CfVirtualList
:items="items"
:item-height="48"
:height="320"
:item-key="(it) => it.id"
>
<template #default="{ item }">
<div class="demo-row">
<strong>{{ item.title }}</strong>
<span class="demo-row__sub">{{ item.desc }}</span>
</div>
</template>
</CfVirtualList>
</template>
<style scoped>
.demo-row { padding: 8px 12px; border-bottom: 1px solid var(--line-1); display: flex; flex-direction: column; }
.demo-row__sub { color: var(--fg-3); font-size: var(--t-11); }
</style> import { CfVirtualList } from '@chufix-design/react';
export default function Demo() {
const items = Array.from({ length: 50_000 }, (_, i) => ({
id: i,
title: `Row #${i + 1}`,
desc: `Lorem ipsum dolor sit amet — ${(i * 7) % 1000}`,
}));
return (
<>
<CfVirtualList items={items} itemHeight={48} height={320} itemKey={(it) => it.id}
>
<div className="demo-row">
<strong>{item.title}</strong>
<span className="demo-row__sub">{item.desc}</span>
</div>
</>
);
} import { CfVirtualList } from '@chufix-design/react';
export default function Demo() {
const items = Array.from({ length: 50_000 }, (_, i) => ({
id: i,
title: `Row #${i + 1}`,
desc: `Lorem ipsum dolor sit amet — ${(i * 7) % 1000}`,
}));
return (
<>
<CfVirtualList items={items} itemHeight={48} height={320} itemKey={(it) => it.id}
>
<div className="demo-row">
<strong>{item.title}</strong>
<span className="demo-row__sub">{item.desc}</span>
</div>
</>
);
} 与 Table / DataGrid 的关系
CfVirtualList 是”纯列表”的虚拟化底座;CfTable / CfDataGrid 当前不内置虚拟化,需要时把数据塞进 CfVirtualList 自定义渲染。后续版本可能把它作为 CfDataGrid 的可选 mode。
API
| 属性 | 类型 | 默认 | 说明 |
|---|---|---|---|
items | T[] | — | 数据数组 |
itemHeight | number | (item, i) => number | — | 行高,固定或函数 |
overscan | number | 5 | 视口外预渲染行数 |
height | number | string | '100%' | 容器高 |
scrollToIndex | number | — | 命令式滚到该 index |
itemKey | (item, i) => string | number | i | 稳定 key |
className | string | — | 根 class |
Imperative API
| 方法 | 说明 |
|---|---|
scrollTo(offset) | 手动滚到 px 偏移 — Vue 用 template ref,React 用 forwardRef 暴露 |
反馈与讨论
VirtualList 虚拟列表 · Discussion