react windowing实现
React Windowing 实现方法
React windowing 是一种优化长列表渲染性能的技术,通过仅渲染可见区域内的元素来减少 DOM 节点数量。以下是几种常见的实现方式:
使用 react-window 库
react-window 是 react-virtualized 的轻量级替代方案,适合大多数列表虚拟化场景。
安装依赖:
npm install react-window
固定高度列表示例:
import { FixedSizeList as List } from 'react-window';
const Row = ({ index, style }) => (
<div style={style}>Row {index}</div>
);
const Example = () => (
<List
height={400}
itemCount={1000}
itemSize={35}
width={300}
>
{Row}
</List>
);
可变高度列表:
import { VariableSizeList as List } from 'react-window';
const rowHeights = new Array(1000)
.fill(true)
.map(() => 25 + Math.round(Math.random() * 50));
const Row = ({ index, style }) => (
<div style={style}>Row {index}</div>
);
const Example = () => (
<List
height={400}
itemCount={1000}
itemSize={index => rowHeights[index]}
width={300}
>
{Row}
</List>
);
使用 react-virtualized
react-virtualized 提供更多功能但体积较大,适合复杂场景。
安装:
npm install react-virtualized
基本实现:
import { List } from 'react-virtualized';
const list = Array(1000).fill().map((_, index) => `Item ${index}`);
function rowRenderer({ key, index, style }) {
return (
<div key={key} style={style}>
{list[index]}
</div>
);
}
const Example = () => (
<List
width={300}
height={400}
rowCount={list.length}
rowHeight={30}
rowRenderer={rowRenderer}
/>
);
自定义实现
对于简单需求可以手动实现虚拟滚动:
function VirtualList({ items, itemHeight, containerHeight }) {
const [scrollTop, setScrollTop] = useState(0);
const startIdx = Math.floor(scrollTop / itemHeight);
const endIdx = Math.min(
items.length - 1,
Math.floor((scrollTop + containerHeight) / itemHeight)
);
return (
<div
style={{ height: containerHeight, overflow: 'auto' }}
onScroll={e => setScrollTop(e.currentTarget.scrollTop)}
>
<div style={{ height: items.length * itemHeight }}>
{items.slice(startIdx, endIdx + 1).map((item, i) => (
<div
key={startIdx + i}
style={{
position: 'absolute',
top: (startIdx + i) * itemHeight,
height: itemHeight
}}
>
{item}
</div>
))}
</div>
</div>
);
}
性能优化建议
- 对于动态内容,使用
useMemo缓存计算结果 - 避免在渲染函数中进行复杂计算
- 对于非常长的列表,考虑分页加载
- 使用
shouldComponentUpdate或React.memo防止不必要的重新渲染
响应式处理
添加响应式支持确保在不同屏幕尺寸正常工作:
const useWindowSize = () => {
const [size, setSize] = useState([0, 0]);
useEffect(() => {
function updateSize() {
setSize([window.innerWidth, window.innerHeight]);
}
window.addEventListener('resize', updateSize);
updateSize();
return () => window.removeEventListener('resize', updateSize);
}, []);
return size;
};
const ResponsiveList = ({ items }) => {
const [width, height] = useWindowSize();
return (
<FixedSizeList
height={height * 0.8}
width={width * 0.9}
itemCount={items.length}
itemSize={50}
>
{Row}
</FixedSizeList>
);
};






