2014-12-02 50 views
0

我有以下代碼片段,它循環遍歷DOM對象數組,運行測試並向節點追加一些文本(如果返回true)。表現形式附加到現有DOM元素數組

$.each(selections, function (i, e) { 
    var test = some_test(e); 
    if(test) { 
     $(e).append('passed'); 
    } 
}); 

雖然此代碼工作正常,在大集很明顯是要執行很多附加到DOM。本文on reasons to use append correctly演示瞭如何追加到DOM是更高性能:

var arr = reallyLongArray; 
var textToInsert = []; 
var i = 0; 
$.each(arr, function(count, item) { 
    textToInsert[i++] = '<tr><td name="pieTD">'; 
    textToInsert[i++] = item; 
    textToInsert[i++] = '</td></tr>'; 
}); 
$('table').append(textToInsert.join('')); 

我的問題是什麼來修改一組現有的DOM元素,而無需調用每個元素.append最高效的方法是什麼?上面的例子演示了創建一個新元素。這是唯一的方法嗎?

+0

我不明白這個問題。 'append'添加一個新的元素。您不應該使用'append'來修改現有的元素 – jasonscript 2014-12-02 01:18:49

+0

一般的做法是儘可能延緩對DOM的修改。 DOM的每個更改都會分別重新繪製。這適用於添加新元素並對現有元素進行更改 – jasonscript 2014-12-02 01:20:15

+0

請注意,您閱讀的文章已超過5年。瀏覽器引擎已經移動。 「更多」已成爲「有時更多」。就你而言,你已經注意到,特定的「優化」甚至不適用。用你已有的東西去做,它最具可讀性。 – Bergi 2014-12-02 01:34:42

回答

0

您可以使用鏈接文章中的技術之一完全重建DOM元素集,然後清除現有集和新的集。但考慮到你已經有了這個集合並且只想調整它的一個子集,你現有的代碼並沒有什麼問題。

1

什麼讓生活DOM操作緩慢主要是它導致大多數操作進行DOM迴流的事實。因此,您應該努力通過減少活動DOM操作的數量來減少DOM迴流量。

如果要操作已經是DOM一部分的多個元素,可以使用的一種策略是臨時從DOM刪除這些節點的父代,操作元素,然後將父節點重新附加到其中它是。

在下面的示例中,我在操作它的行之前先分離表,然後將它重新附加到DOM。這是2次迴流,而不是n次迴流。

var data = [1, 2, 3, 4, 5, 6, 7]; 
 

 
populateCells(document.querySelector('table'), data); 
 

 

 

 
function populateCells(table, data) { 
 
    
 
    var rows = table.rows, 
 
     reAttachTable = temporarilyDetachEl(table); 
 
    
 
    data.forEach(function (num, i) { 
 
    rows[i].cells[0].innerHTML = num; 
 
    }); 
 
    
 
    reAttachTable(); 
 
} 
 

 
function temporarilyDetachEl(el) { 
 
    var parent = el.parentNode, 
 
     nextSibling = el.nextSibling; 
 
    
 
    parent.removeChild(el); 
 
    
 
    return function() { 
 
     if (nextSibling) parent.insertBefore(el, nextSibling); 
 
     else parent.appendChild(el); 
 
    }; 
 
}
<table> 
 
    <tr><td></td></tr> 
 
    <tr><td></td></tr> 
 
    <tr><td></td></tr> 
 
    <tr><td></td></tr> 
 
    <tr><td></td></tr> 
 
    <tr><td></td></tr> 
 
    <tr><td></td></tr> 
 
</table>

0

在談到性能,是分析代碼,這樣你就不必去猜測一個好主意。

下面是一個簡單的測試情況下解決此示例:

http://jsperf.com/most-performant-way-to-append-to-dom-elements

(以及相關小提琴演示的這個可視側:http://jsfiddle.net/f62ptjbf/

該試驗比較了這樣四種可能的方法:(絕不掩蓋所有解決方案)

  1. 追加「通過」作爲文本節點(如您的示例代碼)
  2. 追加「傳遞」爲SPAN節點(稍有改變你的例子)
  3. 建設呈現節點和記錄「通過」一個DOM片段,然後添加到DOM從HTML字符串中的一個附加操作
  4. 從DOM中刪除selection元素,操作它們,然後重新添加到DOM。

這表明[至少在我的Chrome瀏覽器中]最快的方法是在處理之前刪除元素,然後在處理後重新添加到DOM。(#4)

這是另一個測試,顯示[至少在我的Chrome瀏覽器中]將SPAN元素附加文本「傳遞」比追加文本節點更快。

http://jsperf.com/append-variations

基於這些發現,我可以推薦兩個潛在的性能改進代碼:

  1. selection刪除DOM元素操縱在他們面前,並在完成後重新添加。
  2. 附加SPAN與文本「傳遞」,而不是直接附加文本。

但是,如果元素具有共享父級,#1效果最好。性能將是append操作的數量的函數。