虚拟列表专治长列表DOM渲染卡顿,需固定容器高度、精确itemSize、避免sticky、手动处理新增滚动到底部,任一约束失效即引发卡顿。

虚拟列表和长列表不是“有没有关系”,而是虚拟列表就是为长列表而生的——它不解决数据量大本身,但专治长列表带来的 DOM 渲染卡顿。
滚动容器没设固定高度,虚拟列表就失效
虚拟列表依赖 scrollTop 和容器尺寸做可视区域计算。如果 #container 是 height: auto 或 min-height,浏览器无法提供稳定滚动上下文,scrollTop 会跳变或归零,导致起始索引算错、白屏、反复重渲染。
- 必须写死
height(如height: 600px),且配overflow-y: auto - 避免该容器是
position: static的嵌套子元素——父级overflow: hidden或clip-path会裁剪滚动区域 - Vue/React 中用
ref绑定时,确保 ref 指向的是这个带height和overflow的元素,不是外层 wrapper
itemSize 传错或动态变化,滚动直接跳变
等高场景下,itemSize 是核心参数;一旦传 undefined、0 或每次 render 都重新计算,会导致占位高度失准,视口映射偏移,用户滚动时看到内容“闪”或“空一截”。
- 等高:直接传数字,如
itemSize={52} - 变高:不能现场算每项高度,得预存前缀和数组(如
[0, 52, 108, 160, ...]),再用二分查找定位索引 - 别用
Array.prototype.findIndex替代二分——10w 条数据下,每帧遍历一次,CPU 直接飙红
用了 position: sticky,结果完全不 sticky
虚拟列表靠 transform: translateY() 移动内容区,而 position: sticky 依赖最近的滚动祖先元素位置。由于容器本身没滚动,只是子元素被 transform 位移,sticky 失去锚点,自动降级为 relative。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 不要在虚拟列表内部对 item 做
position: sticky - 替代方案:把 sticky 元素提到虚拟列表容器外部,用
position: absolute+ 动态top计算;注意 iOS Safari 下absolute在overflow-scroll容器中仍可能跟随滚动,需实测 - 若必须内嵌,改用监听
scroll+getBoundingClientRect()手动控制显隐,但开销更大
新增数据后不自动滚动到底部
虚拟列表不会响应式更新 scrollTop。哪怕你 push() 一条新消息到数组末尾,滚动条仍停在原位,用户看不到最新内容——这对聊天、日志类场景是硬伤。
- 手动调用
container.scrollTop = container.scrollHeight,但要在 DOM 更新后(如requestAnimationFrame或useEffect的 cleanup 后) - 注意防抖:连续追加多条时,只在最后一次生效,否则滚动抖动
- 如果用
react-window,可结合scrollToItem+align="end";但要确保itemCount已更新,且没因缓存导致索引错位
真正难的不是“用不用虚拟列表”,而是每个细节都得对齐它的约束:固定高度、精确占位、索引 O(log n) 查找、不混入非受控 DOM。漏掉任意一环,它就从性能解药变成卡顿放大器。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










