无限滚动加载时列表抖动怎么办?
我用 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>
你这个抖动大概率是两个原因之一:
第一,列表项高度不固定。如果你的 item 里面有图片或者异步加载的内容,渲染完成后会把下面的内容挤下去,视觉上就是"跳一下"。给图片或者容器设个固定高度或者最小高度就行,留好占位空间。
第二,也是我当年踩的那个坑,你的数据是往数组头部插入的吧?比如用的 unshift 或者把新数据拼到前面。这样会导致已有的 DOM 节点位置整体下移,滚动位置就乱了。
如果是第二种情况,最简单的解法是用 CSS 的 overflow-anchor 属性。给你的列表容器加上这个:
这样浏览器会自动锁定滚动锚点,新内容插入时不会影响当前滚动位置。
或者如果你是往头部插数据,可以用个笨办法,手动修正滚动位置:
我看你代码里用的是 Vue,还要注意一点,key 别用 index,用 item.id 就对了。用 index 当 key 会导致 Vue 复用错 DOM 节点,也会引起奇怪的跳动。
先排查下是不是这几个问题,不行再贴完整代码我帮你看。