前端性能优化:虚拟列表实现原理与实战指南
核心痛点
在处理大规模数据列表时,如果一次性渲染所有 DOM 节点,浏览器会迅速陷入卡顿。想象一下把一万本书全部摆在桌面上,既占地方又难找。最近遇到一个项目,下拉列表有 5000 个选项,全量渲染导致页面直接失去响应,这显然是不可接受的。
反面教材
下面这种写法虽然简单,但在数据量大时是性能杀手:
// 一次性渲染所有数据
function BigList({ items }) {
return (
<ul style={{ height: '400px', overflow: 'auto' }}>
{items.map(item => (
<li key={item.id} style={{ height: '50px' }}>
{item.name}
</li>
))}
</ul>
);
}
渲染 10000 个 DOM 节点会让浏览器资源耗尽,用户电脑风扇狂转也救不了。
虚拟列表的正确姿势
1. 基础实现原理
理解原理有助于排查问题。核心思路是只渲染视口内的元素,并通过 CSS transform 移动内容位置。
import { useState, useRef, useMemo, useCallback } from 'react';
function VirtualList({ items, itemHeight, containerHeight }) {
const [scrollTop, setScrollTop] = useState(0);
const containerRef = useRef(null);
// 计算可见区域
const visibleCount = Math.(containerHeight / itemHeight);
totalHeight = items. * itemHeight;
startIndex = .(scrollTop / itemHeight);
endIndex = .(startIndex + visibleCount + , items.);
visibleItems = ( {
items.(startIndex, endIndex);
}, [items, startIndex, endIndex]);
offsetY = startIndex * itemHeight;
handleScroll = ( {
(e..);
}, []);
(
);
}


