Performant附加到现有DOM元素的数组

时间:2014-12-02 01:13:51

标签: javascript jquery performance dom

我有以下代码,循环遍历DOM对象数组,运行测试并在返回true时向节点附加一些文本。

$.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(''));

我的问题是,在不必为每个元素调用.append的情况下,对一组现有DOM元素进行更改的最高效方法是什么?上面的示例演示了如何创建新元素。这是唯一的方法吗?

3 个答案:

答案 0 :(得分:1)

使实时DOM操作变慢的原因主要在于它导致大多数操作的DOM重排。因此,您应该通过减少实时DOM操作的数量来努力减少DOM回流量。

如果要操作已经是DOM的一部分的多个元素,可以使用的一个策略是临时从DOM中删除这些节点的父节点,操纵元素然后将父节点重新附加到其中是

在下面的示例中,我在操作它的行之前分离表,然后将其重新附加到DOM。那是2的回流而不是回流。

&#13;
&#13;
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);
    };
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

您可以使用链接文章中的一种技术完全重建DOM元素集,然后清除现有集和.append()新集。但鉴于您已经拥有该设置并且只想调整其项目的子集,您的现有代码没有任何问题。

答案 2 :(得分:0)

在谈论性能时,最好对代码进行分析,以便您不必猜测。

以下是围绕此示例的简单测试用例:

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

(和相关的小提琴演示这个视觉方面:http://jsfiddle.net/f62ptjbf/

此测试比较了四种可能的方法:(绝不涵盖所有解决方案)

  1. 将“传递”附加为文本节点(如示例代码)
  2. 将“已通过”附加为SPAN节点(对您的示例略有不同)
  3. 构建一个呈现节点并记录“传递”的DOM片段,然后从HTML字符串中添加到DOM作为单个追加操作
  4. 从DOM中删除selection元素,对其进行操作,然后重新添加到DOM。
  5. 它表明[至少在我的Chrome浏览器副本中]最快的方法是在处理之前删除元素,然后在处理后重新添加到DOM。 (#4)

    以下是另一项测试,显示[至少在我的Chrome副本中]使用“传递”文本附加SPAN元素比附加文本节点更快。

    http://jsperf.com/append-variations

    根据这些调查结果,我建议您对代码进行两项潜在的性能改进:

    1. 在操作之前删除selection中的DOM元素,然后在完成时重新添加。
    2. 附加SPAN文字“已通过”,而不是直接附加文字。
    3. 但是,如果元素具有共享父元素,则#1效果最佳。性能将取决于append操作的数量。