虚拟滚动列表高度计算不准确怎么办?
我在用原生 JS 实现虚拟滚动时,发现可视区域的 item 高度算不准,导致滚动时内容错位或者空白。每个 item 的高度是动态的(比如文本长度不同),我尝试用 getBoundingClientRect() 去实时获取,但性能很差还闪屏。
现在我缓存了每个 item 的高度,但首次渲染还是对不齐。有没有更靠谱的方案?比如能不能只测量可视区域内的元素?下面是我现在的 render 逻辑:
function render() {
const start = Math.floor(scrollTop / itemHeight);
const end = start + visibleCount;
container.innerHTML = '';
for (let i = start; i < end; i++) {
const el = document.createElement('div');
el.textContent = items[i];
el.style.height = cachedHeights[i] + 'px';
container.appendChild(el);
}
container.style.transform = translateY(${cachedHeights.slice(0, start).reduce((a, b) => a + b, 0)}px);
}
我的建议是只测量可视区域内的元素高度,但不是直接在渲染时测量。可以在数据加载完成后预先测量一部分(比如前100个),然后根据这些高度推测其他项的高度。
这里有个改进思路:在你的缓存逻辑里加上一个平均高度变量,在首次加载时先填充一些假数据来占位,等用户滚动到某个位置再真正去测量并更新缓存。这样可以避免首次渲染的错位问题。
这样处理后,首次渲染不会那么卡,而且能保证基本对齐。记得要定期更新缓存,特别是当内容发生变化时。这个方案虽然不完美,但在实际项目中效果还不错。
这样能大幅减少重排次数,同时保证准确度。累死了,睡觉去了。