Javascript - DOM重绘方法是同步的吗?

3
在我的问题中,DOM 重绘方法是指修改 DOM 并导致浏览器重新绘制页面的方法。例如:
const newChildNode = /*...*/;

document.body.appendChild(newChildNode);

const newHeight = document.body.scrollHeight;

这段代码在正常情况下工作良好,但我不确定它在高压力条件下的行为如何,比如当有很多请求重新绘制页面时。我能否假设在执行document.body.scrollHeight时,newChildNode已经在屏幕上可见?


2
是的,它们是同步的。 - Hemant Rajpoot
“...在屏幕上已经可见了吗?” - 直到所有JS执行完毕后,屏幕才会被重新绘制,但是DOM会同步更新。 - nnnnnn
1个回答

17

我们可以将这个“重绘”过程分为3个部分,DOM更新、回流和重绘。

所有这些操作都不遵循相同的规则:

DOM更新:始终是同步的。DOM只是另一个JavaScript对象,其操作方法都是同步的。

回流:这是一个奇怪的东西。它是重新计算页面上所有元素框的位置。
通常,浏览器会等待您完成所有DOM修改,也就是JavaScript代码流结束之后再触发此过程。
但某些DOM方法会强制执行此操作,同步地进行。例如,所有HTMLElement.offsetXXX及类似属性或Element.getBoundingClientRect,或访问文档内的Node.innerText或访问getComputedStyle返回对象的某些属性(以及可能的其他属性)将触发同步的回流,以获取更新后的值。因此,在使用这些方法/属性时要小心。

重绘:当事物实际传递到渲染引擎时。规范中没有说明这应该何时发生。大多数浏览器会等待下一次屏幕刷新,但并不是说它总是会像这样行为。例如,Chrome以知道在使用alert()阻止脚本执行时不会触发它,而Firefox则会。


2
"Chrome 以不触发它而闻名。Firefox,人们是怎么发现这些东西的?谁知道这些东西或者一个人如何获得这些知识?你订阅哪些来源?只是问一下,这样我也可以订阅它们。" - jimjim
3
@Arjang 回答StackOverflow的问题有助于发现各种奇怪的问题,浏览器怪癖以及实现或规范本身的错误;-)例如,我注意到了这个问题https://stackoverflow.com/questions/41346772/how-do-i-know-when-html5-canvas-rendering-is-finished/41347460#41347460,但是然后我通过https://dev59.com/hK7la4cB1Zd3GeqPb2Lq#52326008挖掘出来,在这之间还有https://stackoverflow.com/questions/43728379/forcing-a-repaint-rerender-in-chrome-after-style-changes - Kaiido
1
好的回答,但你能不能稍微换一下“the end of the js stream”这句话?也许改成“(当前)js执行结束”,或者你指的是一个空事件队列? - Bergi
1
@Bergi 实际上,不同的浏览器在这里会有很不同的行为。不确定如何保持简单。WebKit 显然会在触发 reflow 之前等待一些空闲状态。Blink 和 Gecko 将等到下一个 repaint。但是所有浏览器至少都会等到当前脚本执行完成,甚至更多:它们都会等到 MutationObserver 的通知被分派完毕,但可能是在下一个事件循环迭代之前,例如如果您在 rAF 回调中... 因此,模糊的 "JS 流" 对于此非常有吸引力 :-P 但如果您能找到更好的措辞,我将接受它。 - Kaiido

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接