在 React 生态中,有多个成熟的 虚拟列表 npm 库

在 React 生态中,有多个成熟的 虚拟列表 npm 库,无需从零实现复杂的 DOM 复用、滚动计算逻辑。以下是最常用、功能最完善的 3 个库,附带安装、基础用法和核心特性对比,方便你直接选型使用:

一、推荐库排行(按易用性 + 功能完整性)

库名 特点(核心优势) 适用场景 周下载量(npm)
react-window 轻量(仅 3KB)、API 简洁、性能优异,支持固定/可变高度/宽度 大部分场景(列表/表格/下拉框) 约 300 万+
react-virtualized 功能全面(支持表头、排序、筛选、网格)、生态成熟,react-window 的"增强版" 复杂表格、带交互的大型列表 约 200 万+
react-big-list 专为超大数据量(10万+)优化,支持惰性加载、无限滚动,内存占用低 海量数据列表(如日志、报表) 约 5 万+

二、具体使用教程(最常用:react-window)

1. 安装

bash 复制代码
npm install react-window  # 核心库
# 可选:如需滚动条美化、触摸支持,安装辅助库
npm install react-window-infinite-loader  # 无限滚动
npm install react-virtualized-auto-sizer  # 自适应容器尺寸

2. 基础用法:固定高度列表(最常用场景)

jsx 复制代码
import React from 'react';
import { FixedSizeList } from 'react-window';

// 模拟 10 万条数据
const mockData = Array.from({ length: 100000 }, (_, index) => `列表项 ${index + 1}`);

// 渲染单个列表项
const ListItem = ({ index, style }) => {
  return (
    <div style={style} className="list-item">
      {mockData[index]}
    </div>
  );
};

// 虚拟列表组件
const VirtualList = () => {
  return (
    <div style={{ height: '500px', width: '300px', border: '1px solid #eee' }}>
      <FixedSizeList
        height={500}  // 列表容器高度(必须)
        width="100%"  // 列表容器宽度(必须)
        itemCount={mockData.length}  // 总数据量
        itemSize={50}  // 单个列表项高度(固定)
      >
        {ListItem}
      </FixedSizeList>
    </div>
  );
};

export default VirtualList;

3. 进阶用法:可变高度列表

如果列表项高度不固定(如富文本、动态内容),使用 VariableSizeList

jsx 复制代码
import { VariableSizeList } from 'react-window';

// 模拟不同高度的列表项(随机 30-80px)
const getRandomHeight = () => Math.floor(Math.random() * 50) + 30;
const itemHeights = Array.from({ length: 100000 }, getRandomHeight);

const VariableHeightListItem = ({ index, style }) => {
  return (
    <div style={style} className="list-item">
      {mockData[index]}(高度:{itemHeights[index]}px)
    </div>
  );
};

const VariableHeightVirtualList = () => {
  return (
    <div style={{ height: '500px', width: '300px', border: '1px solid #eee' }}>
      <VariableSizeList
        height={500}
        width="100%"
        itemCount={mockData.length}
        itemSize={index => itemHeights[index]}  // 动态返回当前项高度
      >
        {VariableHeightListItem}
      </VariableSizeList>
    </div>
  );
};

4. 无限滚动(结合 react-window-infinite-loader

适合数据量极大、需要分页加载的场景:

bash 复制代码
npm install react-window-infinite-loader
jsx 复制代码
import React, { useState, useCallback } from 'react';
import { FixedSizeList } from 'react-window';
import InfiniteLoader from 'react-window-infinite-loader';

// 模拟异步加载数据(如接口请求)
const fetchData = async (page) => {
  // 实际项目中替换为真实接口
  return new Promise(resolve => {
    setTimeout(() => {
      const newData = Array.from({ length: 20 }, (_, index) => `第 ${page} 页 - 列表项 ${index + 1}`);
      resolve(newData);
    }, 500);
  });
};

const InfiniteVirtualList = () => {
  const [data, setData] = useState([]);
  const [page, setPage] = useState(1);
  const [hasNextPage, setHasNextPage] = useState(true); // 是否还有下一页
  const [isNextPageLoading, setIsNextPageLoading] = useState(false); // 是否正在加载下一页

  // 加载下一页数据
  const loadMore = useCallback(async () => {
    if (isNextPageLoading || !hasNextPage) return;
    setIsNextPageLoading(true);
    try {
      const newData = await fetchData(page);
      setData(prev => [...prev, ...newData]);
      setPage(prev => prev + 1);
      // 模拟只有 5 页数据
      if (page >= 5) setHasNextPage(false);
    } catch (err) {
      console.error('加载失败:', err);
    } finally {
      setIsNextPageLoading(false);
    }
  }, [page, isNextPageLoading, hasNextPage]);

  // 标记某项是否已加载(无限滚动核心)
  const isItemLoaded = index => !hasNextPage || index < data.length;

  // 强制加载下一页(滚动到底部触发)
  const loadMoreItems = useCallback(() => {
    loadMore();
  }, [loadMore]);

  return (
    <div style={{ height: '500px', width: '300px', border: '1px solid #eee' }}>
      <InfiniteLoader
        isItemLoaded={isItemLoaded}
        itemCount={hasNextPage ? data.length + 1 : data.length} // 预留一个"加载中"项
        loadMoreItems={loadMoreItems}
      >
        {({ onItemsRendered, ref }) => (
          <FixedSizeList
            ref={ref}
            onItemsRendered={onItemsRendered} // 监听可视区域项变化,触发加载
            height={500}
            width="100%"
            itemCount={hasNextPage ? data.length + 1 : data.length}
            itemSize={50}
          >
            {({ index, style }) => {
              // 加载中状态
              if (!isItemLoaded(index)) {
                return <div style={style} className="loading">加载中...</div>;
              }
              // 正常数据项
              return <div style={style} className="list-item">{data[index]}</div>;
            }}
          </FixedSizeList>
        )}
      </InfiniteLoader>
    </div>
  );
};

export default InfiniteVirtualList;

三、其他库快速入门

1. react-virtualized(功能更全)

适合复杂场景(如带表头的表格、网格布局):

bash 复制代码
npm install react-virtualized

基础表格示例:

jsx 复制代码
import React from 'react';
import { VirtualizedTable } from 'react-virtualized';

const columns = [
  { key: 'id', label: 'ID', width: 80 },
  { key: 'name', label: '名称', width: 150 },
  { key: 'desc', label: '描述', width: 200 },
];

const data = Array.from({ length: 10000 }, (_, index) => ({
  id: index + 1,
  name: `项目 ${index + 1}`,
  desc: `这是第 ${index + 1} 个项目的描述信息`,
}));

const VirtualizedTableComponent = () => {
  return (
    <div style={{ height: '600px', width: '100%' }}>
      <VirtualizedTable
        width={800}
        height={600}
        headerHeight={40}
        rowHeight={50}
        rowCount={data.length}
        rowGetter={({ index }) => data[index]}
        columns={columns}
      />
    </div>
  );
};

2. react-big-list(超大数据量优化)

bash 复制代码
npm install react-big-list

基础用法:

jsx 复制代码
import React from 'react';
import { BigList } from 'react-big-list';

const data = Array.from({ length: 500000 }, (_, index) => `超大数据项 ${index + 1}`);

const BigVirtualList = () => {
  return (
    <div style={{ height: '500px', width: '300px' }}>
      <BigList
        data={data}
        height={500}
        width="100%"
        itemHeight={40}
        renderItem={({ item }) => <div style={{ padding: '10px' }}>{item}</div>}
      />
    </div>
  );
};

四、选型建议

  1. 优先选 react-window:轻量、易用、性能足够,覆盖 90% 场景(普通列表、下拉选择器、简单表格);
  2. 复杂表格/网格选 react-virtualized:支持表头固定、列排序、筛选等,适合后台管理系统;
  3. 超大数据量(10万+)选 react-big-list:内存占用更低,渲染更流畅。

所有库均支持 React 16+ 版本,且有完善的 TypeScript 类型定义,可放心在生产环境使用~

相关推荐
土豆12503 小时前
React-Draggable 快速上手指南
react.js
什么时候星期五9 小时前
antd 4.x Tabs 点击阻止冒泡
css·react.js
A_one20109 小时前
【无标题】
npm
孟陬11 小时前
我的 AI 工作流 —— project_rules.md 代码规范篇,让 AI 自省自动跑起来
react.js·node.js·bun
霍格沃兹测试开发学社13 小时前
被裁后,我如何实现0到3份大厂Offer的逆袭?(内附面试真题)
人工智能·selenium·react.js·面试·职场和发展·单元测试·压力测试
聊询QQ:2769988515 小时前
楼宇监控系统MCGS6.2仿真程序,带西门子200PLC程序,io表和接线图,设计要求
arcgis
J***793915 小时前
前端在移动端中的React Native Windows
前端·react native·react.js
前端老宋Running17 小时前
我只改了个头像,为什么整个后台系统都闪了一下?
前端·react.js·面试
jenchoi41317 小时前
【2025-11-28】软件供应链安全日报:最新漏洞预警与投毒预警情报汇总
网络·安全·web安全·网络安全·npm
jenchoi41317 小时前
【2025-11-29】软件供应链安全日报:最新漏洞预警与投毒预警情报汇总
网络·安全·web安全·网络安全·npm