react虚拟列表实现及原理小结
作者:光影少年
React虚拟列表是前端性能优化的核心技术之一,尤其在需要渲染上万条数据的表格或列表时很关键,下面就来介绍一下react虚拟列表的实现,感兴趣的可以了解一下
好问题 👍
React 虚拟列表(Virtual List,也叫虚拟滚动 Virtual Scrolling)是 前端性能优化的核心技术之一,尤其在需要渲染上万条数据的表格或列表时很关键。下面我帮你拆解:
🔹 一、为什么要用虚拟列表?
- 普通做法:一次性渲染所有 DOM(比如 1 万条
<div>
),会让浏览器卡顿,首屏加载慢。 - 虚拟列表:只渲染 可视区域的元素,其他部分用空白占位,随着滚动动态更新。
👉 这样 DOM 数量始终保持在几十到几百之间,性能大幅提升。
🔹 二、基本原理
虚拟列表的核心思想是 "只渲染视口范围内的元素 + 占位保持滚动条高度" :
计算容器高度
- 根据数据总数 × 单项高度 = 总高度(生成一个大容器,撑起滚动条)。
计算可见区域
- 监听滚动事件,得到
scrollTop
。 - 根据
scrollTop
/itemHeight
算出应该显示哪些元素。
- 监听滚动事件,得到
渲染可见元素
- 用
absolute
定位,把可见元素放在容器的正确位置。 - 其他元素不渲染,靠容器的
padding
或translateY
占位。
- 用
🔹 三、React 简单实现示例
假设每行高度固定(50px),一共 10000 条数据。
import React, { useState, useRef } from "react"; const rowHeight = 50; // 每项高度 const total = 10000; // 数据总数 const visibleCount = 10; // 可视区显示多少项(容器高度 / rowHeight) const data = Array.from({ length: total }, (_, i) => `Item ${i + 1}`); export default function VirtualList() { const [start, setStart] = useState(0); const containerRef = useRef<HTMLDivElement>(null); const handleScroll = () => { if (!containerRef.current) return; const scrollTop = containerRef.current.scrollTop; const newStart = Math.floor(scrollTop / rowHeight); setStart(newStart); }; const end = start + visibleCount; const visibleData = data.slice(start, end); return ( <div ref={containerRef} onScroll={handleScroll} style={{ height: rowHeight * visibleCount, overflowY: "auto", border: "1px solid #ccc", position: "relative", }} > {/* 大容器:撑起滚动条 */} <div style={{ height: total * rowHeight, position: "relative" }}> {/* 可视区元素 */} {visibleData.map((item, i) => ( <div key={item} style={{ position: "absolute", top: (start + i) * rowHeight, height: rowHeight, lineHeight: `${rowHeight}px`, borderBottom: "1px solid #eee", boxSizing: "border-box", width: "100%", }} > {item} </div> ))} </div> </div> ); }
👉 效果:
- 容器始终只有 ~10 个 DOM 元素。
- 滚动时动态替换显示的元素。
- 看起来就像 10000 条都在 DOM 里,但实际上只有少量渲染。
🔹 四、进阶优化
动态高度支持
- 如果每项高度不同,需要预先计算累积高度(类似 “前缀和”),滚动时二分查找定位。
- 比如
react-virtualized
的CellMeasurer
。
缓冲区(overscan)
- 在可视区域上下多渲染几条,避免快速滚动时白屏。
分片渲染(时间切片)
- 避免一次性渲染太多(
requestIdleCallback
或 React 18startTransition
)。
- 避免一次性渲染太多(
🔹 五、成熟方案
如果自己写太复杂,可以直接用社区库:
- react-window(轻量,推荐,适合固定高度)
- react-virtualized(功能强大,支持动态高度、表格、Grid)
- rc-virtual-list(Ant Design 内部用的虚拟列表)
import { FixedSizeList as List } from "react-window"; <List height={500} itemCount={10000} itemSize={50} width="100%" > {({ index, style }) => ( <div style={style}>Row {index}</div> )} </List>
🔹 六、总结
- 原理:可见区域渲染 + 容器占位 + 滚动时替换数据。
- 优势:DOM 数量固定,内存和渲染性能提升明显。
- 扩展:支持动态高度、缓冲区、时间切片。
- 推荐库:react-window(简单)、react-virtualized(复杂场景)。
到此这篇关于react虚拟列表实现及原理小结的文章就介绍到这了,更多相关react虚拟列表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!