基本原理
- 只渲染可见区域列表项
- 计算可见范围:通过获取视口高度、列表项高度以及当前滚动位置,确定哪些列表项在视口内是可见的。例如,假设视口高度为
viewportHeight
,列表项高度为itemHeight
,当前滚动位置为scrollTop
,则可见列表项的起始索引startIndex
和结束索引endIndex
可以通过Math.floor(scrollTop / itemHeight)
和Math.min(Math.floor((scrollTop + viewportHeight) / itemHeight), totalItems)
计算得出(totalItems
为列表项总数)。
- 虚拟列表渲染:只渲染
startIndex
到endIndex
之间的列表项,而不是渲染整个长列表。在React中,可以通过过滤数据数组,只传递可见范围内的数据给渲染组件。例如:
const visibleItems = data.slice(startIndex, endIndex);
return (
<div>
{visibleItems.map((item, index) => (
<div key={index}>{item}</div>
))}
</div>
);
- 处理滚动事件更新渲染列表部分
- 绑定滚动事件:在React组件中,可以使用
useEffect
钩子在组件挂载时绑定滚动事件,在组件卸载时解绑滚动事件。例如:
import { useEffect } from'react';
useEffect(() => {
const handleScroll = () => {
// 处理滚动逻辑
};
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
- 更新可见范围:在滚动事件处理函数中,重新计算当前滚动位置对应的可见列表项范围。通过
window.pageYOffset
获取当前滚动位置,然后按照上述计算可见范围的方法重新计算startIndex
和endIndex
。
- 触发重新渲染:一旦可见范围更新,通过设置状态(例如
setStartIndex
和setEndIndex
)来触发React组件的重新渲染,从而更新渲染的列表部分,显示新的可见列表项。例如:
import { useEffect, useState } from'react';
const MyList = () => {
const [startIndex, setStartIndex] = useState(0);
const [endIndex, setEndIndex] = useState(10);
useEffect(() => {
const handleScroll = () => {
const scrollTop = window.pageYOffset;
const newStartIndex = Math.floor(scrollTop / itemHeight);
const newEndIndex = Math.min(Math.floor((scrollTop + viewportHeight) / itemHeight), totalItems);
setStartIndex(newStartIndex);
setEndIndex(newEndIndex);
};
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
const visibleItems = data.slice(startIndex, endIndex);
return (
<div>
{visibleItems.map((item, index) => (
<div key={index}>{item}</div>
))}
</div>
);
};