为什么你需要虚拟列表
最近看到一个项目,一个下拉列表有 5000 个选项,全部渲染导致页面卡死。一次性渲染大量 DOM 节点会严重影响性能。
反面教材
// 反面教材:一次性渲染所有数据
function BigList({ items }) {
return (
<ul style={{ height: '400px', overflow: 'auto' }}>
{items.map(item => (
<li key={item.id} style={{ height: '50px' }}>
{item.name}
</li>
))}
</ul>
);
}
// 使用
// <BigList items={Array.from({ length: 10000 }, (_, i) => ({ id: i, name: `Item ${i}` }))} />
渲染 10000 个 DOM 节点会导致浏览器负载过高,影响用户体验。
前端虚拟列表的正确姿势
1. 基础虚拟列表实现
import { useState, useRef, useMemo, useCallback } from 'react';
function VirtualList({ items, itemHeight, containerHeight }) {
const [scrollTop, setScrollTop] = useState(0);
const containerRef = useRef(null);
// 计算可见区域
const visibleCount = Math.ceil(containerHeight / itemHeight);
totalHeight = items. * itemHeight;
startIndex = .(scrollTop / itemHeight);
endIndex = .(startIndex + visibleCount + , items.);
visibleItems = ( {
items.(startIndex, endIndex);
}, [items, startIndex, endIndex]);
offsetY = startIndex * itemHeight;
handleScroll = ( {
(e..);
}, []);
(
);
}
() {
items = .({ : }, ({ : i, : }));
;
}


