vue3动态高度虚拟列表核心是实时测量+缓存+二分查找:用resizeobserver监听dom获取真实高度并缓存,构建累计高度数组,通过二分查找定位可视区起始索引,占位元素撑开总高度,绝对定位渲染可见项,预估高度兜底并增量更新。

Vue 3 中列表虚拟化计算可视区域内动态高度,核心在于不依赖预设值,而是实时采集、缓存并映射每个项的实际渲染高度,再结合滚动位置做精准范围定位。它不是“算出来”的,而是“测出来+查出来+推出来”的组合过程。
1. 高度怎么获取:用 ResizeObserver 监听真实 DOM 尺寸
动态高度无法靠数据字段预先定义,必须等元素挂载并渲染后测量:
- 给每个列表项外层容器(如
<div>)绑定 <code>ref,并在模板中通过el => { if (el) refs.push(el) }收集节点 - 用
ResizeObserver监听每个节点的contentRect.height,首次测量后存入 Map 或响应式对象(如itemHeights.value[item.id] = height) - 注意兼容性:低版本浏览器需引入 polyfill,且避免在 SSR 环境中执行 Observer
- 每次新增/更新高度缓存后,重新生成累计数组(
accumulatedHeights) - 根据当前
scrollTop,用二分查找快速定位可视区起始索引:
找到第一个累计高度 ≥scrollTop的位置,即为首项索引 - 结束索引则由视口高度 + 缓冲区决定(如多渲染上下各 3 条),再反查累计数组边界
- 总高度 = 所有项真实高度之和(
accumulatedHeights[accumulatedHeights.length - 1]) - 用一个绝对定位的
<div class="placeholder"> 设置该高度,作为滚动容器的“骨架”<li>每个可见项用 <code>style="position: absolute; top: Xpx"定位,其中X是其前所有项高度之和(即accumulatedHeights[index]) - 初始渲染用预估高度(如
estimatedHeight = 64)填充累计数组,保证滚动可用 - 监听到新高度后,只更新对应项及后续累计值(避免全量重算)
- 对刚进入可视区但尚未测量的项,先按预估值渲染,待
ResizeObserver触发后再触发重定位(可配合nextTick或防抖)
2. 可视区域怎么确定:靠累计高度数组 + 二分查找
有了每项真实高度,就能构建“累计高度数组”(例如 [0, h0, h0+h1, h0+h1+h2, ...]),它是滚动定位的坐标系基础:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
3. 总高度和偏移怎么设置:用占位元素撑开滚动容器
滚动条存在、滚动行为正常,依赖容器有足够高的“占位”高度:
4. 滚动中如何保持稳定:缓存 + 增量更新 + 防抖回填
用户快速滚动时,部分项尚未测量,不能留白或错位:










