如何快速地从DOM中删除一系列元素?

3

我的布局(简化)如下:

<div class="row">
    <div class="row_section">
    <div class="row_section">
    ...
</div>
<div class="row">
    <div class="row_section">
    ...
</div>
...

我希望找到一种在特定时间间隔内(例如从0到59)清空所有具有class="row"的div的最快方法。

到目前为止,我尝试了很多选项:

$j('div.row').slice(nr_i, nr_s).empty();

令人惊讶的是,这需要比预期更长的时间。

for(i = nr_i; i < nr_s; i++) {
    $j('div.row:eq('+i+')').empty();
}

在一个只有选定范围内存在.row_section div的示例中,

$j('div.row_section').remove();

虽然它是最快的,但仍然不够快。清空60行的部分需要的时间是创建一个新部分的两倍,实际上几乎是三倍。

考虑到创建行涉及比添加一堆部分更多的计算(部分中还有其他东西,并且每行有很多部分),我认为创建行需要更长的时间。

完成原始任务的最快方法是什么,为什么使用最快的解决方案清空所需的时间比创建新的部分要长这么多?

我还想补充一点,行元素可以达到数千个,但非空行从未超过60-80行,每行的行部分可达到数百个。是的,我知道在Web应用程序中这样做是不切实际的,但不得不这样做。


你在哪些浏览器上进行了测试?你不能只说“A比B慢”,而不告诉我们具体的浏览器。特别是这种特殊情况很少在跨浏览器时相同。顺便说一句,我会把它全部删除并重新创建一个新的部分,这也是你提到的。另外一件事:当父元素为display:none时,对live DOM进行的操作速度更快,特别是在连续操作而不是单个步骤中进行操作。 - Mörre
如果你想要速度,就必须停止使用jQuery进行操作,并确保你没有任何.data()项与被删除的对象和jQuery事件处理程序相关。jQuery的问题在于它有很多清理工作要做,以清除所有额外的数据结构,而一个简单的.removeChild()可以非常快速地完成。 - jfriend00
行或行节内没有任何交互式内容,基本上只是一个非常复杂的类似网格的东西。它基本上只是由3-6个类决定大小、颜色、边框等的div组成。 - Bogdan
尝试完全删除它,并通过单步骤中的innerHTML重新创建。从您的示例中看来,您似乎确实要删除某个容器下的几乎所有内容。 - Mörre
@Mörre,我已经选择了一个答案,但我确实尝试了您的建议。结果比所选答案慢一点。似乎innerHTML= ''比删除并再次创建空元素更快。 - Bogdan
显示剩余3条评论
4个回答

2
var elements = document.getElementsByClassName("row");
for(i=0; i<elements.length; i++)
{
    elements[i].innerHTML = '';
}

这可能是最快的方法。实际上与我尝试过的相比飞快。看来我应该停止无节制地使用jQuery了。 - Bogdan
实际上,它是最快的,从我过去获得的1000ms或更多缩短到了85ms。 - Bogdan
在可能的情况下使用DOM API是我发现的最快的方法。 - John McNulty

1
为什么不试一下:

function removeRow(fromV, toV){
  $('div.row').each(function(i){
    if(i >= fromV && <= toV){ 
      $(this).remove();
    }
  });
}

另一次尝试:

function removeRow(fromV, toV){
      var i = fromV;
      while(i <= toV){
          $('div.row').eq(i).remove();
          i++;
      }
    }

1
因为那样我将浏览所有的行,这可能达到数千甚至数万行才能到达60行的部分。这对我来说似乎不是很高效,尽管我可以尝试快速完成它。 - Bogdan
这与我尝试过的某些东西相似(参见第二个示例),但它并不像John的答案那样快。看起来这里的解决方案是根本不使用jQuery。 - Bogdan

1
根据jQuery代码,slice方法执行本地的slice,然后调用jQuery.merge方法。而merge方法对当前jQuery集合中的每个元素进行循环。
因此,在您的第二个示例中,您只进行了一次循环。在您的第一个示例中,您进行了切片,然后进行了合并循环,然后进行了第二次循环以将empty方法应用于您集合中的所有元素。
我认为最快的解决方案是使用导航器querySelectorAll方法(当您使用标准CSS选择器时,jQuery会使用此方法)。尝试构建一个大的CSS选择器,如div.row:eq(1), div.row:eq(2), div.row:eq(3) ...,并使用它来执行以下操作:$(selector).empty()

有道理;我以为它会更聪明一些。我应该更仔细地阅读关于“slice”的文档。 - Bogdan

0

另一种选择是,不会产生额外的查询选择器解析:

var divs = $j('div.row');
for(var i = nr_i; i < nr_s; i++) {
    divs.eq(i).empty();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接