无限滚动加载时列表抖动是怎么回事?
我在用 React 做一个消息列表的无限滚动,每次滚动到底部就加载更多数据,但新数据一进来整个列表会突然跳一下,体验特别差。明明是 append 数据,为啥还会抖?
我试过用 scrollTop 手动保持位置,也用了固定 item 高度,但问题还在。是不是因为虚拟滚动没做?还是说我的加载时机有问题?
useEffect(() => {
const handleScroll = () => {
if (containerRef.current.scrollTop + containerRef.current.clientHeight >= containerRef.current.scrollHeight - 10) {
loadMore();
}
};
containerRef.current?.addEventListener('scroll', handleScroll);
return () => containerRef.current?.removeEventListener('scroll', handleScroll);
}, []);
在 WordPress 主题开发里也经常遇到类似情况,一般我会用
position: absolute固定滚动容器的高度和位置。你可以试试给容器加上overflow-anchor: none来禁用浏览器的自动滚动恢复。另外 loadMore 函数里记得先设置一个加载状态标志,避免重复请求。数据加载完再更新列表时,可以用
requestAnimationFrame包一下 DOM 更新操作,让渲染更平滑。如果还是不行,考虑把虚拟滚动加进去,不过这得花点时间重构。累了就先休息会儿,这活真磨人。
你用的是固定高度item,但新数据进来后scrollHeight增加了,浏览器默认行为会把滚动条"重置"到顶部附近(取决于容器布局),所以会跳。
核心解决思路:加载前记录scrollHeight,加载后根据差值调整scrollTop。
另一个问题:你的滚动监听没做节流,滚动到底部那一下可能触发多次,导致数据重复加载或状态混乱。加载锁(loadingRef)记得加上。
还有,加载时机判断可以稍微宽松一点,比如距离底部50px再触发,别等到完全到底,否则网络慢的时候很容易出问题:
代码放这了,试一下应该就不抖了。