滚动到底部(和强制回流性能问题)

Posted

技术标签:

【中文标题】滚动到底部(和强制回流性能问题)【英文标题】:Scroll to bottom (and forced reflow performance issues) 【发布时间】:2021-08-29 05:10:19 【问题描述】:

在收到消息(WebSocket,不重要)后,我正在尝试使用 vanilla JS 滚动到 div 的底部(在我的可滚动网页内)。该消息在div 中添加了一个新元素el,我希望div 滚动到el

div.append(el); // or ...array
// clear div if too many messages here,
//  using while (childNodes.length > ...) firstChild.remove();
div.scroll...(el);
使用div.scrollTo(0, div.scrollHeight)(编辑:或div.scrollTop = div.scrollHeight)会很好,如果它不是那么慢的话 - 我经常收到很多消息,而且每当我必须用@强制重排时它基本上会冻结浏览器987654329@. 使用el.scrollIntoView()(编辑:或其变体)实际上要快得多(从简短的未受过教育的分析会话中累积,scrollTo 的 20 秒和scrollIntoView 的 0.6 秒,给定相对相同的负载),但是,我的 @987654333 @ 恰好位于可滚动页面内,scrollIntoView 使整个页面滚动以使 el 出现在视图中。基本上,我希望它滚动到div 的底部,甚至在屏幕外(或达到类似的效果)。

对于这个问题还有其他解决方案吗,或者是否可以修复前两个变体之一?


更新:

使用div.scrollTo(0, Number.MAX_SAFE_INTEGER); 和类似功能仅适用于 Chrome,不适用于 Firefox。虽然运行速度很快(与第二个解决方案相比)。类似的变体 div.scrollTop = Number.MAX_SAFE_INTEGER 实际上由于某种原因表现很差。

【问题讨论】:

【参考方案1】:
div.scrollIntoView(false);

这会将您带到 div 的底部。

【讨论】:

抱歉,将div 滚动到视图中不是我想要的。 如果您的意思是el.scrollIntoView(false)(问题中的el 表示添加到可滚动div 的消息),添加false(表示alignToTop 参数)不会解决问题中提出的问题。【参考方案2】:

试试div.scrollTop = div.scrollHeight:

var contents = document.querySelector('.contents');
const before = new Date().getTime();
contents.scrollTop = contents.scrollHeight;
const after = new Date().getTime();
const diff = after -  before;
console.log(`Took $diff milliseconds`);
.contents
  height:200px;
  overflow-y:auto;

.section
  height:197px;
  border:1px solid;
<div class="contents">
  <div class="section">1</div>
  <div class="section">2</div>
  <div class="section">3</div>
</div>

【讨论】:

使用相同/相似的消息运行分析 10 秒,使用 scrollHeight(您的方法使用 =)运行 2301 毫秒,使用 scrollIntoView 运行 24 毫秒。使用 Chrome,查看线路附近的 Sources 中的时间。强制回流是一件大事。

以上是关于滚动到底部(和强制回流性能问题)的主要内容,如果未能解决你的问题,请参考以下文章

虚拟滚动技术 --- 解决加载大量列表DOM导致页面卡顿

在表格视图和性能中滚动底部

Web前端性能优化-重绘与回流

使用动态高度将视图固定到底部

前端性能优化 —— reflow(回流)和repaint(重绘)

Javascript性能优化之节流函数