glownight

返回

满分答案#

大列表卡顿的核心原因是一次性渲染大量 DOM 节点,阻塞主线程。 优化方案按优先级:虚拟滚动(核心)、懒加载、分页、列表项 memo 优化、减少渲染节点、时间切片、避免复杂计算,其中虚拟滚动是解决超大数据量最有效的方案


一、卡顿的根本原因#

  1. 一次性渲染成百上千个 DOM 节点
  2. 主线程被 JS 执行阻塞,页面交互、滚动、输入都会卡顿
  3. 重排重绘(reflow)成本极高

二、React 项目实战优化方案(从必用到进阶)#

1. 虚拟滚动(最有效、首选)#

只渲染可视区域内的节点,可视区域外的 DOM 全部不渲染,节点数从 10000 → 10~20。

成熟库(直接用)

  • react-window(轻量)
  • react-virtualized(功能全)
  • antd / antd-table 自带 virtual 属性
import { FixedSizeList } from 'react-window';

const VirtualList = ({ data }) => {
  return (
    <FixedSizeList
      height={500}        // 可视区域高度
      width="100%"
      itemCount={data.length}
      itemHeight={50}     // 每项高度
    >
      {({ index, style }) => (
        <div style={style}>{data[index]}</div>
      )}
    </FixedSizeList>
  );
};
jsx

2. 列表项使用 React.memo 缓存#

防止父组件更新导致所有列表项重复渲染

const Item = React.memo(({ item }) => {
  return <div>{item.name}</div>;
});
jsx

3. 分页加载 / 滚动加载(懒加载)#

不一次渲染所有数据:

  • 分页
  • 滚动到底加载更多(无限滚动)
useEffect(() => {
  // 监听滚动,触底加载下一页
  window.addEventListener('scroll', handleScroll);
}, []);
jsx

4. 使用正确、稳定的 key#

千万不要用 index 做 key,会导致:

  • 错误复用
  • 大量不必要的 DOM 销毁重建
  • 列表 Diff 极慢
// ✅ 正确
{item.id}

// ❌ 错误
{index}
jsx

5. 时间切片(Time Slicing)#

利用 React Fiber 把渲染任务分片执行,不阻塞主线程:

  • ReactDOM.createRoot(React 18 默认开启)
  • 配合 useDeferredValue / Suspense
import { useDeferredValue } from 'react';

const deferredList = useDeferredValue(list);
jsx

6. 减少列表项内部计算#

useMemo 缓存列表项内部的过滤、排序、格式化

const content = useMemo(() => formatData(item), [item]);
jsx

7. 图片懒加载#

列表中的图片延迟加载,减少渲染压力。


三、优化优先级#

  1. 虚拟滚动(1000条以上数据必用)
  2. 分页/无限加载
  3. 列表项 memo 优化
  4. 稳定 key
  5. 时间切片(React 18)
  6. 减少内部计算 & 图片懒加载

四、一句话总结#

大列表卡顿是因为一次性渲染太多 DOM。 最优方案是虚拟滚动,只渲染可视区域; 其次是分页、懒加载、memo 缓存、稳定 key, 配合 React 18 时间切片,可彻底解决卡顿问题。


总结#

万条数据不卡顿 = 虚拟滚动 + memo + 正确key + 时间切片

大列表渲染卡顿时,React 项目里怎么优化?
作者 glownight
发布于 2026年1月25日