如何实现react-window FixedSizeList随视口滚动 隐藏组件自带滚动条
react-window绑定视口滚动、隐藏自带滚动条实现方案
核心逻辑
react-window默认以自身内部容器作为滚动载体,要实现视口滚动驱动列表渲染、隐藏组件自带滚动条,只需要做三件事:
- 禁用组件内部容器的滚动能力,彻底隐藏自带滚动条
- 在外层生成和列表总高度一致的占位块,让视口生成和原生页面一致长度的滚动条
- 监听视口滚动事件,把滚动偏移同步给react-window实例,驱动它渲染对应可视区域的内容
实现代码
以下是基于你提供的示例修改的、可直接运行的FixedSizeList实现:
import { useRef, useEffect, useState } from 'react'; import { FixedSizeList } from 'react-window'; // 列表配置,统一抽离方便计算 const ITEM_SIZE = 35; const ITEM_COUNT = 38; const LIST_TOTAL_HEIGHT = ITEM_COUNT * ITEM_SIZE; const Row = ({ index, style }) => <div style={style}>Row {index}</div>; export default function ScrollBindList() { const listRef = useRef(null); const wrapperRef = useRef(null); const [listTop, setListTop] = useState(0); useEffect(() => { // 计算列表初始位置,页面加载、窗口尺寸变化时更新 const updateListPosition = () => { if (!wrapperRef.current) return; const rect = wrapperRef.current.getBoundingClientRect(); setListTop(rect.top + window.scrollY); }; // 监听视口滚动,同步偏移给列表组件 const handleWindowScroll = () => { if (!listRef.current) return; const scrollY = window.scrollY; // 计算列表实际需要滚动的偏移,做边界兜底 let targetScrollTop = scrollY - listTop; targetScrollTop = Math.max(0, Math.min(targetScrollTop, LIST_TOTAL_HEIGHT - window.innerHeight)); // 调用组件内置方法同步滚动位置 listRef.current.scrollTo(targetScrollTop); }; updateListPosition(); window.addEventListener('scroll', handleWindowScroll, { passive: true }); window.addEventListener('resize', updateListPosition); return () => { window.removeEventListener('scroll', handleWindowScroll); window.removeEventListener('resize', updateListPosition); }; }, [listTop]); return ( // 外层占位容器,高度等于列表总高度,撑出视口滚动条 <div ref={wrapperRef} style={{ height: LIST_TOTAL_HEIGHT, position: 'relative' }}> {/* 粘性定位容器,把列表固定在视口可视区域 */} <div style={{ position: 'sticky', top: 0, height: '100vh' }}> <FixedSizeList ref={listRef} height={window.innerHeight} itemCount={ITEM_COUNT} itemSize={ITEM_SIZE} width="100%" // 隐藏自带滚动条 style={{ overflow: 'hidden' }} > {Row} </FixedSizeList> </div> </div> ); }
FixedSizeGrid适配方法
Grid组件逻辑完全通用,只需要调整几个点:
- 占位容器的宽高设置为
列数*列宽、行数*行高,对应Grid的总内容尺寸 - 如果需要绑定横向视口滚动,额外监听
scrollX事件,调用实例的scrollTo({ scrollLeft, scrollTop })方法同步横向偏移 - Grid组件本身的
width设为视口宽度、height设为视口高度,同样加overflow: hidden样式
注意事项
- 滚动事件必须加
passive: true配置,避免阻塞主线程影响滚动流畅度 - 如果页面有固定顶部导航,只需要把粘性容器的
top值改为导航高度,列表高度改为calc(100vh - 导航高度),计算滚动偏移时同步减去导航高度即可 - 不需要额外安装第三方依赖,纯原生API配合react-window自带的实例方法就能实现,性能和原生滚动基本一致
内容的提问来源于stack exchange,提问作者dev
相关产品推荐
相关产品推荐

