定高版本
1 "use client"; 2 import React, { useCallback, useMemo, useState } from "react"; 3 4 interface IProps { 5 list: any[]; 6 fixedHeight: number; 7 } 8 9 // Fixed height 10 const VirtualView = (props: IProps) => { 11 const { list, fixedHeight } = props; 12 13 const [startIndex, setStarIndex] = useState(0); 14 const [endIndex, setEndIndex] = useState(10); 15 16 const targetList = list.slice(startIndex, endIndex); 17 const visibleNum = targetList.length; 18 19 const { containerHeight, viewHeight } = useMemo(() => { 20 return { 21 viewHeight: visibleNum * fixedHeight, 22 containerHeight: list.length * fixedHeight, 23 }; 24 }, [list, fixedHeight, visibleNum]); 25 console.log(startIndex, endIndex, visibleNum); 26 27 const maxIndex = list.length - visibleNum; 28 const handleScroll = useCallback( 29 (e: any) => { 30 const scrollTop = e?.target?.scrollTop as number; 31 let nextIndex = Math.floor(scrollTop / fixedHeight); 32 nextIndex = Math.min(maxIndex, nextIndex); 33 setStarIndex(nextIndex); 34 setEndIndex(visibleNum + nextIndex); 35 }, 36 [fixedHeight, setStarIndex, setEndIndex, maxIndex, visibleNum] 37 ); 38 return ( 39 <div 40 onScroll={handleScroll} 41 className={`virtual-list-view relative w-1/2 overflow-y-auto border-2 border-l-indigo-800`} 42 style={{ maxHeight: viewHeight }} 43 > 44 <div className="list-phantom" style={{ height: containerHeight }}></div> 45 <div className="absolute top-0" style={{ top: startIndex * fixedHeight }}> 46 {targetList.map((item) => { 47 return ( 48 <div key={item.id} className={""} style={{ height: fixedHeight }}> 49 <span className="name">{item.name}</span> 50 <p className="">{item.body}</p> 51 </div> 52 ); 53 })} 54 </div> 55 </div> 56 ); 57 }; 58 59 export default VirtualView;
展示元素个数: visibleNum = enindex - startIndex
组件容器:virtual-list-view
因为每行item高度固定, 可以计算的到容器的高度fixedHeight * visibleNum
并注入onscroll回调,let nextIndex = Math.floor(scrollTop / fixedHeight); 根据scrollTop 距离计算当前应该展示的startIndex 和 endIndex
支撑容器高度的元素: list-phantom 根据 list.length * fixedHeight 一开始就能得到整个容器的高度 列表元素, 根据startIndex 和 endIndex 对数组数据做切分, 获得应该展示的元素数据, 其实在最后start, end 前后可以再多展示几行数据做缓冲, 避免渲染不连续,但是要记得调整列表元素的top 或者其他位移属性, 嫌麻烦, 这里就不做了 const targetList = list.slice(startIndex, endIndex);
需要调整top 或其他属性移动到 scrollTop 的距离, 也就是startIndex * fixedHeight
不定高度的版本
adding...
标签:nextIndex,const,list,列表,React,startIndex,visibleNum,fixedHeight,滚动 From: https://www.cnblogs.com/xlno/p/17718235.html