For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/llms-full.txt, and this page is available as Markdown at https://ifhover.github.io/leaf-ui/components/virtual-list.md.

VirtualList 虚拟列表

流畅浏览大量列表内容。

基本用法

basic.tsx
import { VirtualList } from '@ifhover/leaf-ui';

import { useState } from 'react';

export function VirtualListBasic() {
  const [items] = useState(() =>
    Array.from({ length: 10000 }, (_, index) => ({
      id: String(index),
      name: `项目 ${index + 1}`,
    })),
  );
  return (
    <VirtualList
      items={items}
      itemKey={(item) => item.id}
      height={240}
      estimateSize={44}
      renderItem={(item) => <div style={{ padding: '12px 16px' }}>{item.name}</div>}
    />
  );
}

更多用法

advanced.tsx
import { Button, Space, VirtualList } from '@ifhover/leaf-ui';

import { useRef, useState } from 'react';

export function VirtualListDynamic() {
  const list = useRef<import('@ifhover/leaf-ui').VirtualListHandle>(null);
  const [items] = useState(() =>
    Array.from({ length: 1000 }, (_, index) => ({
      id: String(index),
      text: '长度不同的内容。 '.repeat((index % 3) + 1),
    })),
  );
  return (
    <Space direction="vertical" align="stretch">
      <Button variant="outline" onClick={() => list.current?.scrollToIndex(500, 'start')}>
        跳至第 501 项
      </Button>
      <VirtualList
        ref={list}
        items={items}
        itemKey={(item) => item.id}
        height={220}
        estimateSize={60}
        renderItem={(item) => (
          <div style={{ padding: 16 }}>
            <strong>#{item.id}</strong>
            <p style={{ margin: '4px 0' }}>{item.text}</p>
          </div>
        )}
      />
    </Space>
  );
}

使用说明

itemKey 必须稳定。estimateSize 用于初始估计,之后自动测量行高。SSR 输出确定的初始窗口,挂载后根据容器调整。

类型

组装数据、定义回调和使用 ref 时,可以导入这些类型。

import type { VirtualListHandle, VirtualListProps } from '@ifhover/leaf-ui';

VirtualListHandle API

属性类型默认值说明
elementHTMLDivElement | null必填滚动容器元素
scrollToIndex(index: number, align?: 'auto' | 'start' | 'center' | 'end') => void必填滚动至项目
scrollToOffset(offset: number) => void必填滚动至偏移量

VirtualListProps API

属性类型默认值说明
itemsreadonly T[]必填数据项目,保持 key 唯一且稳定
itemKey(item: T, index: number) => Key必填提取稳定的项目标识
renderItem(item: T, index: number) => ReactNode必填自定义项目内容
heightnumber320高度,数字按像素计算
estimateSizenumber | ((item: T, index: number) => number)40预估项目尺寸,挂载后测量实际尺寸
overscannumber5可见区域外预渲染数量
emptyContentReactNode—空列表内容
horizontalbooleanfalse横向虚拟列表