2014-11-05 55 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

相關問題