如何设置react-window VariableSizeList宽度100%且高度自适应?
问题原因与修复方案
核心问题分析
- AutoSizer的依赖条件缺失:
AutoSizer必须依赖父容器有明确的宽高约束(比如固定高度、百分比高度且父级存在可计算尺寸),否则它无法正确计算可用空间,会传给VariableSizeList宽高为0,直接导致页面空白。 - 虚拟列表的适配逻辑错误:你原有的
getPageHeight方法依赖固定的window.innerWidth,但使用AutoSizer后,列表宽度应该跟随容器动态计算,两者不匹配会导致页面尺寸异常。
修复步骤
步骤1:给父容器添加尺寸约束
修改MemoizedPDFPreview.module.css中的样式,确保包裹AutoSizer的容器有明确的尺寸:
/* 基础预览容器样式 */ .previewBody { width: 100%; min-height: 100vh; /* 让容器至少占满视口高度 */ overflow: hidden; } /* 全屏预览容器样式 */ .previewFsBody { width: 100%; height: 100vh; overflow: hidden; }
步骤2:正确适配AutoSizer与VariableSizeList
更新renderPdfList方法,让列表尺寸跟随AutoSizer的计算结果,同时动态调整PDF页面的宽高:
const renderPdfList = () => { if (pdf && pageViewports) { return ( <AutoSizer> {({ width, height }) => ( <VariableSizeList width={width} height={height} estimatedItemSize={100} itemCount={pdf.numPages} // 直接在itemSize中根据当前宽度计算页面高度 itemSize={(index) => { const pageViewport = pageViewports[index]; const scale = width / pageViewport.width; return pageViewport.height * scale; }} > {({ index, style }) => ( <TeXPDFPage index={index} // 确保子页面宽度匹配列表容器,继承高度样式 style={{ ...style, width: width }} projId={projId} projAttribute={projAttribute} /> )} </VariableSizeList> )} </AutoSizer> ); } else { return <div>loading...</div>; } };
- 移除原来独立的
width状态,改用AutoSizer返回的动态宽度计算页面高度,避免窗口尺寸变化时出现适配问题。 - 给
TeXPDFPage的样式补充width: width,确保页面宽度与列表容器完全匹配。
步骤3:窗口尺寸变化适配(可选)
如果需要在窗口 resize 时实时更新列表尺寸,可以给AutoSizer添加回调:
<AutoSizer onResize={({ width, height }) => { // 可在此处添加额外的尺寸监听逻辑,比如保存尺寸到状态 }}> {/* ... 列表内容 ... */} </AutoSizer>
特殊场景:完全自适应内容高度
如果不需要虚拟滚动,只想让容器高度随所有PDF页面总高度自适应,可以直接渲染所有页面(适合PDF页数较少的场景):
const renderPdfList = () => { if (pdf && pageViewports) { const containerWidth = document.getElementById('pdfContainer')?.clientWidth || window.innerWidth; return ( <div style={{ width: '100%' }}> {Array.from({ length: pdf.numPages }).map((_, index) => { const pageViewport = pageViewports[index]; const scale = containerWidth / pageViewport.width; const height = pageViewport.height * scale; return ( <TeXPDFPage key={index} index={index} style={{ width: containerWidth, height }} projId={projId} projAttribute={projAttribute} /> ); })} </div> ); } else { return <div>loading...</div>; } };
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

