scrollIntoView在forEach循环后触发过早问题排查
问题解决:scrollIntoView 执行后滚动位置自动重置
问题根源
虽然forEach是同步执行的,但浏览器的DOM重排(reflow)操作会延迟到当前任务队列结束后才触发。当你把li元素的display从none恢复为默认值时,容器的高度会发生变化,这个高度调整的重排操作会在scrollIntoView执行之后完成,最终导致滚动位置被重置回容器顶部。手动在控制台执行时,DOM已经完成重排,所以滚动表现正常。
修复方案
把scrollIntoView的调用推迟到浏览器完成下一次重绘之后,用requestAnimationFrame实现即可:
function clearSizeSearch() { document.querySelectorAll('li.empty-search').forEach(e => e.remove()); document.querySelectorAll('ul.size-ranks li').forEach(e => e.style.display = ''); // 推迟到浏览器下一次渲染周期执行滚动 requestAnimationFrame(() => { const activeElem = document.querySelector('ul.size-ranks li.active'); if (activeElem) { // 增加元素存在判断,避免页面状态异常时报错 activeElem.scrollIntoView(); } }); }
额外说明
requestAnimationFrame会把回调函数加入浏览器的渲染队列,确保DOM重排、重绘全部完成后再执行滚动操作,从根源上避免滚动位置被后续DOM更新重置。额外添加的元素存在性判断,能避免页面状态异常时出现控制台报错。
内容的提问来源于stack exchange,提问作者GlenVaughan
相关产品推荐
相关产品推荐

