不依赖第三方,借用react18api和原生JS实现一个虚拟滚动列表,如果你的项目比较小,又不想引入第三方的框架,可以拿去用;
style样式
.record_list{// 这里是动态高度height: calc(100% - 116px);overflow-x: hidden;overflow-y: auto;position: relative;.render_box{// 布局设为绝对定位,后续使用translateY动态改变position: absolute;top: 0;left: 0;width: 100%;}}
核心HTML
{/* 外层盒子 屏幕高度 可滚动*/}<div className={style.record_list} ref={scrollBoxRef} onScroll={virtualBoxScroll}>{/* 空盒子 撑起高度*/}<div style={{ height: `${recordList.length * renderItemHeight}px` }}></div>{/*实际渲染的列表记录*/}<div className={style.render_box} style={{ transform: `translateY(${startIndex * renderItemHeight}px)` }}>{renderList.map((item: any) => {return <CallLogCard key={item.id} item={item}></CallLogCard>})}</div></div>
逻辑代码
/*****************初始化变量*****************/// 1.初始配置let expendCount = 4; // 多渲染数量let screenHeight = 700; // 渲染屏幕高度const renderItemHeight = 60; // 每条数据的固定高度// 2.滚动容器Refconst scrollBoxRef = useRef<any>(null);// 3.开始,结束渲染索引const [endIndex, setEndIndex] = useState(20);const [startIndex, setStartIndex] = useState(0);// 4.动态更新渲染列表const renderList = useMemo(() => recordList.slice(startIndex, endIndex),[startIndex, endIndex, recordList],);/*****************方法*****************/// 滚动监听const virtualBoxScroll = () => {// 滑动距离const scrollDistance = scrollBoxRef.current.scrollTop;// 计算新索引/*Math.floor()一个数向下取整*/const startIndex = Math.floor(scrollDistance / renderItemHeight);/*Math.ceil()一个数向上取整*/const endIndex =startIndex + Math.ceil(screenHeight / renderItemHeight) + expendCount; // 多渲染5条// 更新索引setStartIndex(startIndex);setEndIndex(endIndex);};// 历史记录列表const [recordList, setRecordList] = useState<any>([]);// 获取历史记录列表;const pullHistoryPage = () => {/*ajax*/setRecordList([...res.list]);};// 初始化滚动屏幕高度const handleInitScreenHeight = () => {screenHeight = scrollBoxRef.current.clientHeight;/*Math.ceil()一个数向上取整*/expendCount = Math.ceil(screenHeight / renderItemHeight);};useEffect(() => {// 拉取数据pullHistoryPage();// 初始化定位handleInitScreenHeight();}, []);