在 React 中实现虚拟列表(Virtual List)是优化长列表性能的关键技术,它通过只渲染可视区域内的项目来减少 DOM 节点数量,提升页面流畅度。以下是几种常见的实现方法:
import React, { useState, useRef, useEffect } from 'react';
const BasicVirtualList = ({
items, // 所有列表数据
itemHeight = 50, // 每个项目的固定高度
visibleCount = 10 // 可视区域可显示的项目数量
}) => {
const [startIndex, setStartIndex] = useState(0);
const listRef = useRef(null);
const containerRef = useRef(null);
// 计算可视区域内的项目范围
const handleScroll = () => {
if (!containerRef.current) return;
// 滚动距离 / 项目高度 = 起始索引
const scrollTop = containerRef.current.scrollTop;
const newStartIndex = Math.floor(scrollTop / itemHeight);
// 避免频繁更新
if (newStartIndex !== startIndex) {
setStartIndex(newStartIndex);
}
};
// 计算需要渲染的项目(可视区域 + 缓冲区)
const endIndex = Math.min(
startIndex + visibleCount + 5, // 额外渲染5个作为缓冲区
items.length
);
const visibleItems = items.slice(startIndex, endIndex);
// 计算偏移量(让可视项目显示在正确位置)
const offsetTop = startIndex * itemHeight;
useEffect(() => {
const container = containerRef.current;
if (container) {
container.addEventListener('scroll', handleScroll);
return () => container.removeEventListener('scroll', handleScroll);
}
}, [startIndex]);
return (
<div
ref={containerRef}
style={{
height: `${visibleCount * itemHeight}px`, // 可视区域高度
overflow: 'auto',
position: 'relative',
border: '1px solid #ccc'
}}
>
{/* 占位容器,维持滚动条高度 */}
<div
style={{
height: `${items.length * itemHeight}px`,
position: 'absolute',
top: 0,
left: 0,
right: 0
}}
/>
{/* 实际渲染的项目区域 */}
<div
ref={listRef}
style={{
position: 'absolute',
top: offsetTop,
left: 0,
right: 0
}}
>
{visibleItems.map((item, index) => (
<div
key={item.id}
style={{
height: `${itemHeight}px`,
padding: '12px',
borderBottom: '1px solid #eee',
boxSizing: 'border-box'
}}
>
{item.content}
</div>
))}
</div>
</div>
);
};
export default BasicVirtualList;
手动计算可视区域内的项目,通过滚动事件动态更新渲染范围。
核心原理:
startIndex
)top
偏移到正确位置对于高度不固定的项目,需要动态计算每个项目的高度并缓存。
核心改进:
heights
缓存每个项目的实际高度offsets
数组存储累计高度,快速计算任意位置的偏移量对于复杂场景,推荐使用经过优化的成熟库:
轻量级虚拟列表库,专注于性能和简单API。
import { FixedSizeList as List } from 'react-window';
const ReactWindowList = ({ items }) => {
const Row = ({ index, style }) => (
<div style={style}>
{items[index].content}
</div>
);
return (
<List
height={500} // 可视区域高度
width="100%" // 宽度
itemCount={items.length} // 总项目数
itemSize={50} // 每个项目高度
>
{Row}
</List>
);
};
功能更全面的库,支持网格、表格等复杂布局。
import { List } from 'react-virtualized';
const ReactVirtualizedList = ({ items }) => {
const rowRenderer = ({ index, key, style }) => (
<div key={key} style={style}>
{items[index].content}
</div>
);
return (
<List
height={500}
width="100%"
rowCount={items.length}
rowHeight={50}
rowRenderer={rowRenderer}
/>
);
};
超轻量级实现,适合简单场景。
react-window
react-virtualized
react-virtualized
或 react-window
的网格组件虚拟列表的核心是减少DOM节点数量和精准计算可视区域,实际项目中可根据列表复杂度和性能要求选择合适的实现方式。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。