开发预览 更新于 2026-05-10

VirtualList 虚拟列表

只渲染可见行 + overscan 的虚拟列表,支持固定 / 变高行;十万行无掉帧。

基础用法

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
src/App.vue
<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

属性类型默认说明
itemsT[]数据数组
itemHeightnumber | (item, i) => number行高,固定或函数
overscannumber5视口外预渲染行数
heightnumber | string'100%'容器高
scrollToIndexnumber命令式滚到该 index
itemKey(item, i) => string | numberi稳定 key
classNamestring根 class

Imperative API

方法说明
scrollTo(offset)手动滚到 px 偏移 — Vue 用 template ref,React 用 forwardRef 暴露

反馈与讨论

VirtualList 虚拟列表 的讨论

0
0 / 600
正在加载评论...