React实现虚拟列表
Posted 不想掉头发啊!!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React实现虚拟列表相关的知识,希望对你有一定的参考价值。
/*
思路:
1.通过 useRef 获取元素,缓存变量。
2.useEffect 初始化计算容器的高度。截取初始化列表长度。这里需要 div 占位,撑起滚动条。
3.通过监听滚动容器的 onScroll 事件,根据 scrollTop 来计算渲染区域向上偏移量, 这里需要注意的是,当用户向下滑动的时候,为了渲染区域,能在可视区域内,可视区域要向上滚动;当用户向上滑动的时候,可视区域要向下滚动。
4.通过重新计算 end 和 start 来重新渲染列表。
*/
const App = () =>
const content = useRef(null)
const scrollBox = useRef(null)
const scrollList = useRef(null)
const [data, setData] = useState([])
const [start, setStart] = useState(0)
const [end, setEnd] = useState(0)
const scrollInfo = useRef(
boxHeight: 500,
itemHeight: 50,
renderCount: 0,
bufferSize: 8
)
useEffect(() =>
// 获取数据
const res = new Array(2000).fill(1).map((item, index) => item + index)
setData(res)
// 获取渲染的个数
const itemHeight, boxHeight, bufferSize = scrollInfo.current
const renderCount = Math.ceil(boxHeight / itemHeight) + bufferSize
scrollInfo.current.renderCount = renderCount
// 获取首次渲染时截取数据的索引
setEnd(renderCount)
, [])
// 处理滚动
const handleScroll = () =>
const itemHeight, boxHeight, bufferSize, renderCount = scrollInfo.current
// 获取元素中的内容”超出“元素上边界”的高度
const scrollTop = scrollBox.current
// 获取开始截取数据的值
const bufferVal = bufferSize / 2
const newStartIndex = Math.floor(scrollTop / itemHeight)
// 获取结束截取的数据的值
const newEndIndex = newStartIndex + renderCount
// 如果发生变化,那么就重新渲染
if (newEndIndex !== end || newStartIndex !== start)
setStart(newStartIndex)
setEnd(newEndIndex)
const currentOffset = scrollTop - (scrollTop % itemHeight)
scrollList.current.style.transform = `translate3d(0, $currentOffsetpx, 0)` /* 偏移,造成下滑效果 */
// 对数据进行截取进行渲染
const renderList = data.slice(start, end)
const itemHeight = scrollInfo.current
return <div ref=content>
<div ref=scrollBox className="scroll_box" onScroll=handleScroll>
/* 撑开div 让其滚动 */
<div className="scroll_hold" style=height: `$data.length * itemHeightpx`></div>
<ul className="list" ref=scrollList>
renderList.map(item => <li key=item style=height: '50px'>item</li>)
</ul>
</div>
</div>
.scroll_box
overflow-y: scroll;
position: relative;
height: 500px;
.scroll_hold
position: absolute;
left: 0;
top: 0;
right: 0;
z-index: -1;
.list
position: absolute;
left: 0;
right: 0;
top: 0;
li
width: 100%;
list-style: none;
padding: 5px;
以上是关于React实现虚拟列表的主要内容,如果未能解决你的问题,请参考以下文章