首页 > 解决方案 > 强制同步布局如何影响浏览器事件循环?

问题描述

浏览器中的事件循环一般包括这些步骤,重复:

  1. 执行脚本(任务)
  2. 执行微任务
  3. 渲染更新(如果浏览器准备好呈现下一帧)

el.offsetHeight同时在我们的代码中,读取(此处为完整列表)之类的属性可能会导致浏览器重新计算样式并同步执行布局,以返回最新值。这会改变事件循环吗?例如,给定这个脚本块:

el.style.width = "200px"; // invalidate the style
el.offsetHeight; // forced synchronous layout
foo();
console.log("script end");

通常,整个块是一个任务,浏览器将它执行到最后一行,处理所有微任务,然后在必要时渲染更新。但是第二行触发同步布局,事件循环会是怎样的呢?它是暂停执行,跳到步骤 3),渲染更新,然后在下一个滴答中继续执行其余代码,还是只是执行布局并仍在步骤 1) 中?

标签: javascriptbrowserevent-loop

解决方案


布局在事件循环处理模型1中没有定义,因此强制这样的布局对其没有任何影响。

发生的情况是,大多数浏览器会在计算之前等待它们真正需要这些更新的值,所以这意味着如果没有任何请求,它们会等到事件循环的“更新渲染”步骤被调用,这之后可能是一些事件循环迭代,以及之后的许多微任务检查点。

通过调用它,您只是在促成该事件,如果您以后不弄脏布局,就不会造成任何不良后果。

但是,如果您(或任何脚本)在强制回流后弄脏了布局,则在渲染之前将发生新的回流,这意味着浏览器将不得不计算多次而不是一次,这可能会减慢您的页面,而且在复杂的页面上。

1. W3C 定义的ResizeObserver API确实包含在他们的规范中,但是他们没有定义 HTML 的事件循环处理,他们的定义也没有处理这里讨论的强制回流的情况。


推荐阅读