2014-11-05 52 views
3

有人告诉我,在将多个元素插入到DOM中时,首先分离目标元素,插入元素,然后将其追加回DOM,会更有效。我想知道为什么。为什么分离和追加效率比直接更改html更有效?

例如,

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更高效,并且由多少意义?

+0

可能是因为这可以确保只有一个文档回流。你试过了吗? – Alnitak 2014-11-05 21:57:04

+2

需要'join()'字符串数组首先工作。自己运行一个性能测试来解决这个问题http://jsperf.com – charlietfl 2014-11-05 21:58:24

+0

@charlietfl我将字符串更改为JQuery对象。这会工作吗?好吧,我会进行性能测试。但我仍然想知道为什么一个比另一个更有效率。 – 2014-11-05 22:10:24

回答

5

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

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

所有回流有一个理由,其被保持在回流状态 对象(以及可能发生变异,如下所述)。回流原因 控制框架的回流过程中如何反应,是继 之一:

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

Incremental,当帧树中的某些内容发生变化时;例如,当从网络中读取更多内容时,或者某些脚本操纵DOM时。增量回流针对帧层次结构中的单个帧。在增量回流期间,框架可以假定框架内的所有约束条件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回流。一旦从DOM中删除<ul>,并将其添加到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'); 
} 
+1

链接有一个不同的用例,在循环中执行多个附加。与OP所做的不完全相同 – charlietfl 2014-11-05 22:08:43

+0

但是当别人告诉他做他正在做的事时,可能是别人想的。我猜在这种情况下,方法1会更有效率。 – 2014-11-05 22:11:59

+1

http://jsperf.com/detach-before-html – Musa 2014-11-05 23:56:58

相关问题