react大列表实现优化

 更新时间:2026年09月22日 08:37:13   作者:光影少年  
React 大列表优化中,是最常见、最有效的优化方案之一,本文就来介绍一下大列表如何实现优化,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧<BR>

React 大列表优化中,虚拟列表(Virtual List) 是最常见、最有效的优化方案之一。

为什么需要虚拟列表

假设有 10 万条数据:

{
  data.map(item => (
    <Row key={item.id} {...item} />
  ))
}

React 会一次性生成:

<div>...</div>
<div>...</div>
...
(100000个节点)

问题:

  • DOM 节点过多
  • 首次渲染慢
  • 浏览器布局(Layout)和绘制(Paint)耗时
  • 滚动卡顿
  • 内存占用高

即使用户当前只能看到 20 条数据,浏览器仍然维护 10 万个 DOM。

虚拟列表核心思想

只渲染可视区域内的数据。

例如:

总数据:100000条

当前屏幕:
----------------
第100条
第101条
...
第120条
----------------

实际上只渲染:

100 ~ 120

共 20 个节点。

滚动时:

向下滚动
100~120
↓
110~130

销毁旧节点,复用或创建新节点。

DOM 数量始终维持:

20 ~ 30个

而不是:

100000个

实现原理

假设:

总数 = 100000
每行高度 = 50px

总高度:

100000 * 50
= 5000000px

容器:

<div className="container">
  <div className="phantom"></div>
  <div className="content"></div>
</div>

结构:

container
│
├── phantom
│     高度5000000px
│
└── content
      真正渲染的数据

1. 创建占位元素(phantom)

<div
  style={{
    height: data.length * itemHeight
  }}
/>

作用:

让滚动条看起来像真的有 10 万条数据。

滚动条长度正常

但实际上没有渲染全部节点。

2. 监听滚动

const handleScroll = (e) => {
  const scrollTop = e.target.scrollTop;
};

例如:

scrollTop = 5000px

3. 计算开始索引

公式:

startIndex = Math.floor(
  scrollTop / itemHeight
);

例如:

5000 / 50
= 100

说明:

当前从第100条开始显示

4. 计算结束索引

可视区域:

containerHeight = 500px

可显示:

500 / 50

= 10条

结束索引:

endIndex = startIndex + visibleCount;
100 + 10
= 110

5. 截取数据

const visibleData =
  data.slice(
    startIndex,
    endIndex
  );

只渲染:

{
  visibleData.map(...)
}

6. 偏移内容位置

如果直接渲染:

100~110

会出现在顶部。

需要移动到正确位置:

offsetY =
  startIndex * itemHeight;
100 * 50
= 5000px
<div
  style={{
    transform: `translateY(${offsetY}px)`
  }}
>

最终效果:

滚动5000px

↓
显示第100条

图解

总高度 5000000px
┌──────────────────┐
│                  │
│ phantom          │
│                  │
└──────────────────┘
      ↑
当前滚动到这里
      ↓
translateY(5000px)
┌──────────────────┐
│ 第100条          │
│ 第101条          │
│ 第102条          │
│ ...              │
└──────────────────┘

简易实现

function VirtualList() {
  const itemHeight = 50;
  const visibleCount = 10;

  const [start, setStart] = useState(0);

  const handleScroll = (e) => {
    const scrollTop = e.target.scrollTop;

    setStart(
      Math.floor(scrollTop / itemHeight)
    );
  };

  const visibleData = data.slice(
    start,
    start + visibleCount
  );

  return (
    <div
      style={{
        height: 500,
        overflow: "auto"
      }}
      onScroll={handleScroll}
    >
      <div
        style={{
          height:
            data.length * itemHeight,
          position: "relative"
        }}
      >
        <div
          style={{
            transform: `translateY(${
              start * itemHeight
            }px)`
          }}
        >
          {visibleData.map(item => (
            <div
              key={item.id}
              style={{
                height: itemHeight
              }}
            >
              {item.name}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

优化:缓冲区(Buffer)

实际项目不会只渲染可视区域。

例如:

可视区域:10条
上缓冲:5条
下缓冲:5条

实际渲染:

20条

这样滚动时不会频繁白屏。

const buffer = 5;

start =
  Math.max(
    0,
    startIndex - buffer
  );

end =
  startIndex +
  visibleCount +
  buffer;

动态高度怎么办?

上面算法要求:

固定高度

如果每一项高度不同:

50px
80px
120px
60px
...

就不能简单用:

scrollTop / itemHeight

需要维护:

高度缓存表

例如:

[
  50,
  130,
  250,
  370,
  ...
]

通过二分查找定位:

scrollTop
↓
对应哪一项

这就是很多虚拟列表库复杂的地方。

React常用虚拟列表库

1.react-window 官网

作者:Brian Vaughn

特点:

  • 轻量
  • 性能好
  • 推荐
npm install react-window

2.react-virtualized 官网

特点:

  • 功能最全
  • 支持表格
  • 支持动态高度

缺点:

  • 包较大

3.TanStack Virtual 官网

特点:

  • React/Vue/Solid 通用
  • 现代项目使用较多

面试回答模板

当面试官问:

React 大列表如何优化?

可以这样回答:

大列表的性能瓶颈主要在于 DOM 数量过多导致的渲染、重排和内存开销。常见方案是使用虚拟列表。虚拟列表的核心思想是只渲染当前可视区域的数据,而不是全部数据。通过监听 scroll 事件,根据 scrollTop 计算 startIndex 和 endIndex,仅渲染这一段数据,同时利用一个等高占位元素撑开滚动高度,并通过 translateY 将当前渲染内容移动到正确位置。这样无论数据量是 1 万条还是 10 万条,页面中实际 DOM 数量都保持在几十个,从而大幅提升性能。

到此这篇关于react大列表实现优化的文章就介绍到这了,更多相关react大列表优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于Node的React图片上传组件实现实例代码

    基于Node的React图片上传组件实现实例代码

    本篇文章主要介绍了基于Node的React图片上传组件实现实例代码,非常具有实用价值,需要的朋友可以参考下
    2017-05-05
  • 详解使用React制作一个模态框

    详解使用React制作一个模态框

    这篇文章主要介绍了详解使用React制作一个模态框,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • 在React项目中使用Eslint代码检查工具及常见问题

    在React项目中使用Eslint代码检查工具及常见问题

    这篇文章主要介绍了在React项目中使用Eslint代码检查工具及常见问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • react如何将字符串转义成html语句

    react如何将字符串转义成html语句

    这篇文章主要介绍了react如何将字符串转义成html语句问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • React函数组件和类组件的区别及说明

    React函数组件和类组件的区别及说明

    这篇文章主要介绍了React函数组件和类组件的区别及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • React 的 getInitialState实现组件状态初始化

    React 的 getInitialState实现组件状态初始化

    本文主要介绍了React 的 getInitialState实现组件状态初始化,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-08-08
  • React中遍历数组生成标签问题

    React中遍历数组生成标签问题

    这篇文章主要介绍了React中遍历数组生成标签问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • 基于react框架使用的一些细节要点的思考

    基于react框架使用的一些细节要点的思考

    下面小编就为大家带来一篇基于react框架使用的一些细节要点的思考。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • 一文详解React Redux使用方法

    一文详解React Redux使用方法

    这篇文章主要介绍了一文详解React Redux使用方法,文章围绕主题展开详细的内容戒杀,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • react component changing uncontrolled input报错解决

    react component changing uncontrolled in

    这篇文章主要为大家介绍了react component changing uncontrolled input报错解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12

最新评论