首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么删除元素要比添加元素花费更多的时间?

为什么删除元素要比添加元素花费更多的时间?
EN

Stack Overflow用户
提问于 2017-09-11 15:04:15
回答 5查看 1.8K关注 0票数 20

我有一个有很多行的表(比如10.000行)。

(注意:我知道拥有这么大的表是没有意义的,但我想了解一下下面的行为)。

当我收到新数据时,我想先清除行。奇怪的是,清空表格所需的时间比从头构建行要长得多。使用html("")或普通的JS innerHTML = ""清除表行需要1.5分钟,比构建行本身需要不到一秒的时间要多得多。

所以我的问题是:

  • 为什么删除元素比添加元素需要更多时间?“幕后”发生了什么?

(请注意,我的问题是为什么是 one,我不是在寻找可能的解决方法)。

更新

我注意到表行和单元格应用了浮动定义,当我删除浮动时,表在一个实例中被清空。

我仍然很想理解为什么使得删除行的速度变得如此之慢。

这里有一把小提琴:https://jsfiddle.net/maaikeb/t5pduuue/

在Chrome中,清空表格需要25秒,将其附加到DOM只需要23 ms。

*我读了下面的帖子,但它们更多地讨论了可能的解决方案,而较少讨论为什么删除元素比添加它们需要更多的时间,当您删除它们时实际发生了什么

jQuery empty is very slow

jQuery empty is very slow

What is the best way to remove a table row with jQuery?

Deleting table rows in javascript

jquery - fastest way to remove all rows from a very large table

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2017-09-30 17:12:15

如果你问为什么清空表比追加表多花1000倍的时间,那么,答案是不应该的:这是一个bug。

你可以发现重要的性能差异取决于浏览器,它的版本,jQuery的版本或操作系统,但25s对23ms太多了。它看起来比你遇到O(N^2)操作的地方要好。低于这个价格,人们就会开票,浏览器的开发者也会承认他们的存在。

无论如何,删除元素并不总是比添加元素更快。我们的直觉告诉我们,销毁应该比创建更快,但当涉及到操作DOM时,这不一定是正确的。jQuery和浏览器都需要做额外的工作来取出元素。

如果您查看一下当前(3.2.1)的jQuery append() function实现,您会发现它基本上所做的就是使用原生JS方法appendChild()。另一方面,jQuery empty() function (html()使用empty())需要遍历所有内部元素,并注意移除每个内部元素的相关数据(例如事件),以防止内存泄漏。

而且,如果你只使用普通的JS,浏览器在删除元素时仍然需要检查一大堆东西。如果你想了解浏览器的内部结构,你可以查看这个Firefox issue

不管你用的是removeChild()innerHtml还是textContent(),浏览器总是需要重新计算样式和布局:检查this one in Chromium

这种bug是很常见的。如果你在Chromium中搜索关键字"removeChild“和"slow”来查找问题,你会得到一个漂亮的long list。有时,它们由于引入回归的修复而来来去去,就像在涉及浮动元素的this case中一样。This other one对你来说可能特别有趣,因为它证明了一些bug与你选择的删除元素的方法无关,而且就像你的例子一样,当复杂的CSS规则应用于这些元素时,它就会出现(建议浏览器触发回流)。

我无法在Firefox和Chrome中重现你的问题,所以我无法解决25秒或1.5分钟的确切原因,但它似乎真的是在最近的版本中修复了一个错误。如果您仍然拥有相同的旧版本并可以重现它,那么检查一下以相反的顺序删除元素(从lastChild开始)是否有帮助。也许您会避免在移除后重新计算所有浮动同级的位置。

下一次,也许你想打开一张罚单,看看他们是如何找到错误并修复它的。它会满足你的好奇心,并且你可以学到很多关于浏览器内部的知识!

票数 1
EN

Stack Overflow用户

发布于 2017-09-14 17:16:45

我假设你在IE上的表现很差。

我要说这是因为$.empty方法在一个循环中为表中每个删除的元素调用removeChild,而该方法在IE中的性能总是很差-参见this article for short case study的一些性能比较和解决方案。

无论你用大的DOM做什么,你的在IE上都会有很差的性能。This article on appendChild in large DOM on IE就是一个例子,说明社区仍然对这个简单的事实感到困惑。:)

票数 2
EN

Stack Overflow用户

发布于 2017-09-18 21:12:28

您可以使用hide()和show(),而不是遍历整个DOM、移除并重新呈现。这是因为检索隐藏列也非常容易,所以速度快且性能好。请找到有用的代码片段。

代码语言:javascript
复制
//did based on checkbox here update to ur requirement hide() callback remains same.

$("input:checkbox:not(:checked)").each(function() {
    var column = "table ." + $(this).attr("name");
    $(column).hide();
});

$("input:checkbox").click(function(){
    var column = "table ." + $(this).attr("name");
    $(column).toggle();
});
代码语言:javascript
复制
td, th {
    padding: 6px;
    border: 1px solid black;
}

th {
    background-color: #f0eae2;
    font-weight: bold;
}

table {
    border: 1px solid black;
}
代码语言:javascript
复制
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<p><input type="checkbox" name="first_name" checked="checked"> First Name 
  <input type="checkbox" name="last_name"> Last Name 
  <input type="checkbox" name="email" checked="checked"> Email</p>

<table id="report">
<thead>
<tr>
 <th class="first_name">First Name</th>
 <th class="last_name">Last Name</th>
 <th class="email">Email</th>
</tr>
</thead>
<tbody>
<tr>
 <td class="first_name">Larry</td>
 <td class="last_name">Hughes</td>
 <td class="email">larry@gmail.com</td>
</tr>
<tr>
 <td class="first_name">Mike</td>
 <td class="last_name">Tyson</td>
 <td class="email">mike@gmail.com</td>
</tr>
</tbody>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46149924

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档