附加DocumentFragment会引起多少次回流?

10
使用DocumentFramgment可以让我们将DOM元素相互连接而不会导致浏览器重排(即在离线DOM树上工作)。很多类库,如jQuery,都使用文档片段来提高性能。
文档片段可以具有复杂的结构。例如,假设它代表着以下内容:
<div>
   <span>
       <a href='asd'>asd</a>
   </span>
   <span>
       <a href='asd2'>asd2</a>
   </span>
   <div>
       <div>
          Hello World
       </div>
   </div>
</div>

或者是包含多个子元素的文档片段:
<h2>Title 1</h2>
<p>Lorem ipsum.</p>
<p>Lorem ipsum.</p>
<h2>Title 2</h2>
<p>Lorem ipsum.</p>
<p>Lorem ipsum.</p>

通常情况下,当我们完成文档片段的构建后,会将其附加到主DOM树上。这样做会发生多少次回流?这取决于文档片段的直接子元素数量吗?
更新:我收到了谷歌Chrome团队的Addy Osmani的回复:
只有一次DOM回流。PS:我们更倾向于将回流称为布局,因为它基本上是触发页面布局/重绘的事件。

2
我敢打赌第一个问题的答案是“一”。 - John Dvorak
这个可能会有帮助:https://developers.google.com/speed/articles/javascript-dom。 - jeremy
2
@JanDvorak 我猜所有浏览器都只会执行一次回流,但这不是实现的责任(即在一般情况下无法验证)吗? - Denys Séguret
@dystroy 猜得不错。你能证明这不是规范所要求的吗? - John Dvorak
1个回答

7
每次触发引起DOM回流的操作时,都会发生一次单独的DOM回流过程。 我们可以从此文章中了解到:

这种模式让我们创建多个元素并将其插入到DOM中,从而触发单个回流。 它使用了一种称为DocumentFragment的东西。 我们在DOM之外(因此在流之外)创建了一个DocumentFragment。 然后,我们在其中创建并添加多个元素。 最后,我们将DocumentFragment中的所有元素移动到DOM中,但只触发一次回流。

各种操作可能会导致DOM回流,包括向文档附加新元素。 使用DocumentFragment的目的是能够在单个操作中将内容附加到DOM并导致单个回流过程。

根据这篇文章,我们可以阅读到:

有时候,重新呈现文档中的单个元素可能需要重新呈现其父元素以及其后面的任何元素。

但是,所有这些回流操作都将在单个回流过程中发生。

我创建了一个演示来说明这一点。 使用Chrome的时间轴,我们可以清楚地看到渲染在单个块中进行。

enter image description here


你有“引起单次回流”的来源吗? - Denys Séguret
感谢您的时间和回答。然而,这更像是一种猜测而不是一个答案。“我认为根据添加的内容,回流过程可能会更加昂贵或便宜。” 如果您声称进行了多次回流,请问能否展示一下(从规格说明、小提琴或任何类似的工具)? - Benjamin Gruenbaum
好的,文章中提到重新流动单个元素可能会重新流动其父元素以及其后面的任何元素。但是,这将在单个重新流程中完成。 - plalx
非常好的实证过程!您能确认这在其他浏览器中也是这种行为吗? - Benjamin Gruenbaum
我不能确定,但如果你考虑一下,由于浏览器在单个线程中执行,因此单个操作存在多个回流过程的唯一方式是,如果它们允许使用类似于“setTimemout”的方法将回流分批运行,让一些客户端代码在批处理之间执行。然而,如果执行其他修改DOM的代码会发生什么?在这种情况下,所有内容都必须重新计算,因此我非常确定回流始终作为原子操作发生。 - plalx
WebKit引擎的Chromium分支实际上确实使用了多个线程来渲染dDOM(如果我没记错的话)。其他引擎可能会使用不同的线程,例如一个用于JavaScript,另一个用于页面。 - Benjamin Gruenbaum

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