无限滚动加载时列表抖动怎么办?

___怡冉 阅读 7

我用 IntersectionObserver 做了个无限滚动,但每次加载新数据后页面会突然跳一下,体验很糟糕。明明没动滚动位置,怎么就抖了?

试过给容器加固定高度、用虚拟滚动库,但要么没效果要么太重。是不是我结构写得有问题?

<div id="scroll-container" style="height: 80vh; overflow-y: auto;">
  <div v-for="item in list" :key="item.id" class="item">
    {{ item.title }}
  </div>
  <div id="sentinel"></div>
</div>
我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
技术晓燕
我之前踩过这个坑,折腾了好久才发现原因。

你这个抖动大概率是两个原因之一:

第一,列表项高度不固定。如果你的 item 里面有图片或者异步加载的内容,渲染完成后会把下面的内容挤下去,视觉上就是"跳一下"。给图片或者容器设个固定高度或者最小高度就行,留好占位空间。

第二,也是我当年踩的那个坑,你的数据是往数组头部插入的吧?比如用的 unshift 或者把新数据拼到前面。这样会导致已有的 DOM 节点位置整体下移,滚动位置就乱了。

如果是第二种情况,最简单的解法是用 CSS 的 overflow-anchor 属性。给你的列表容器加上这个:

#scroll-container {
overflow-anchor: auto;
}

.item {
overflow-anchor: none;
}


这样浏览器会自动锁定滚动锚点,新内容插入时不会影响当前滚动位置。

或者如果你是往头部插数据,可以用个笨办法,手动修正滚动位置:

// 插入数据前记录
const oldHeight = container.scrollHeight;

// 插入数据后修正
this.$nextTick(() => {
const newHeight = container.scrollHeight;
container.scrollTop += newHeight - oldHeight;
});


我看你代码里用的是 Vue,还要注意一点,key 别用 index,用 item.id 就对了。用 index 当 key 会导致 Vue 复用错 DOM 节点,也会引起奇怪的跳动。

先排查下是不是这几个问题,不行再贴完整代码我帮你看。
点赞
2026-02-28 16:00