为什么分离和追加比直接更改html更有效?

时间:2014-11-05 21:50:21

标签: jquery

有人告诉我,在向DOM中插入多个元素时,首先分离目标元素,插入元素然后将其追加到DOM会更有效。我想知道原因。

例如,

HTML

<div id="main">
  <ul class="list"></ul>
</div>

的jQuery

var arrayOfElements = [$("<li> .... </li>"), $("<li> .... </li>"), ... , $("<li> ... </li>")]

# Appraoch 1
$(".list").html(arrayOfElements);

# Approach 2
$(".list").detach().html(arrayOfElements).appendTo(".main");

为什么appraoch 2的效率更高,意义何在?

1 个答案:

答案 0 :(得分:5)

向DOM添加一系列元素时,每个元素都会触发浏览器重排页面。将一个元素添加到已经准备好而不在DOM上的页面上,然后将其附加到DOM只会导致页面的一次重排。

来自:http://www-archive.mozilla.org/newlayout/doc/reflow.html

  

所有回流都有一个原因,它保持在回流状态   对象(并且可以变异,如下所述)。回流的原因   控制框架在回流期间的反应方式,并且是其中之一   以下内容:

文章接着列出了重排的原因,以下就是这样一个原因:

  

增量,当帧树中的某些内容发生变化时;例如,当从网络读取更多内容时,或者某些脚本操纵DOM。增量回流针对帧层次结构中的单个帧。在增量回流期间,帧可以假设在&#39;&#39;内没有计算出from above'' (for example, available width) have changed; instead, something的约束。框架已更改,可能会对框架层次结构产生自下而上的影响。

至于性能改进,我会把它留给John Resig。

Browser         Normal (ms) Fragment (ms)
Firefox 3.0.1   90          47
Safari  3.1.2   156         44
Opera 9.51      208         95
IE 6            401         140
IE 7            230         61
IE 8b1          120         40

来源:http://ejohn.org/blog/dom-documentfragments/

你的例子虽然有些缺陷。

var arrayOfElements = [$("<li>....</li>"), $("<li>....</li>"), $("<li>...</li>")];

应写成:

var arrayOfElements = ["<li>....</li>", "<li>....</li>", "<li>....</li>"].join('');

其次

// Approach 1
$(".list").html(arrayOfElements);

在两个例子之间,这个 MAY 实际上更好。为什么呢?

由于:

// Approach 2
$(".list").detach().html(arrayOfElements).appendTo("#main");

最多可能导致(并且可能会)2次回流。一旦将<ul>从DOM中删除,一次将其附加到DOM。 Approach 1可能导致2次(或更多次)回流,因为.html必须删除当前子级,然后附加第二组。决定因素是.html方法是顺序追加每个元素还是一次追加所有元素作为一个DOM元素。但至少它更容易理解。并且它最多可以从DOM中移除一个元素,从而可能减少重排的影响。

然而,这两种方法都优于以下方法:

var arrayOfElements = ["<li>....</li>", "<li>....</li>", "<li>....</li>"];
$('.list').children().remove();
for (var i = 0; i < arrayOfElements.length; i++) {
    $(arrayOfElements[i]).appendTo('.list');
}