【问题标题】:Efficiently removing textnodes from the DOM从 DOM 中有效地删除文本节点
【发布时间】:2012-06-06 08:30:16
【问题描述】:

在不涉及太多细节的情况下,我正在使用 javascript 清理表格内的空白。我需要删除大量的文本节点。当涉及到 IE9 时,这似乎是我脚本中的瓶颈。

以下所有方法都可以完成这项工作,但它们会导致严重的减速。

domNode.removeNode(true);
domNode.nodeValue = "";
domNode.parentNode.removeChild(domNode);

有没有办法进行批量删除或将它们隐藏在 dom 等中。只是更快。

我也在 textnodes 上试过这个:

domNode.innerHTML = '';

虽然它执行得很快,但文本节点似乎没有被它分阶段。

另外,我需要保留事件绑定,因此在整个表上替换 .innerHTML 似乎并不是一个选项。虽然它的运行速度确实快了大约 5 倍。

更新: 建议解决方案的粗略基准:

//around 480ms
stripWhitespaceTextNodes(domNode);

//around 640ms
parent.removeChild(domNode);
stripWhitespaceTextNodes(domNode);
parent.insertBefore(domNode, nextNode);

//around 700ms
tables[i].style.visibility = 'hidden';
stripWhitespaceTextNodes(domNode);
tables[i].style.visibility = 'visible';

//around 1140ms
tables[i].style.display = 'none';
stripWhitespaceTextNodes(domNode);
tables[i].style.display = 'block';

这是在 4 个表上完成的,其中一个表有 1500 行。

stripWhitespaceTextNodes() 函数的关键是删除文本节点,这似乎是瓶颈,这是我的各种尝试。

domNode.parentNode.removeChild(domNode);
domNode.removeNode(true);
domNode.nodeValue = ""; // <-- CURRENTLY THIS ONE IS THE TOP RUNNER
domNode.replaceWholeText('');
domNode.deleteData(0, domNode.length);

var txtNode = document.createTextNode("");
domNode.parentNode.replaceChild(txtNode, domNode);
parent.insertBefore(domNode, nextNode);

//fast but doesn't work
domNode.innerHTML = '';

【问题讨论】:

  • 我会对细节感兴趣。为什么需要从表格中删除空白文本节点,它们不会影响显示?
  • 他们在 IE9 中做。有关这些详细信息,请参阅此问题。 stackoverflow.com/questions/9895095/… 至于为什么我不能在服务器端修复它,那就是另一个长篇故事了......
  • 您是否尝试过使用 domNode.innerText = '' 或 domNode.textContent = '' 删除文本节点?
  • 还在为这个而苦恼吗?我得说你坚持让它发挥作用。
  • 请记住,选项 B [...].nodeValue = ""; 实际上并没有删除节点。这就是它更快的原因。

标签: javascript dom


【解决方案1】:

这样做的常用技巧是在进行重大更改之前从 DOM 中删除您正在执行这些操作的容器,然后在完成后将其放回原处。

所以在你的情况下,这可能是:

var table = /* ...get a reference to the table...*/;
var nextNode = table.nextSibling; // May be null, that's fine
var parent = table.parentNode;
parent.removeChild(table);
/* ...clean up the text nodes... */
parent.insertBefore(table, nextNode);

即使树与页面的 DOM 分离,事件处理程序仍保持连接状态,因此当树被放回时它们会在那里。

【讨论】:

  • 如果你只是想防止重绘,table.style.display="none" 应该足够了。
  • @Bergi:与其说是 paints,不如说是 reflows。但是,是的,绝对的,OP 应该像上面一样尝试使表格不可显示,并选择最适合他/她的表格。
  • 区别在哪里?当然,当 js 使用 css 值计算时,可能会出现没有重绘的重排 - 不是这里 - 但它们都不应该发生在隐藏元素上。
  • 我可能对 DOM 重绘假设过激了。由于某种原因,在表格上设置 display none 只会使执行时间翻倍......?
  • @Serhiy:答案中建议的分离呢?
【解决方案2】:

您可以这样做的一种方法是克隆整个表并“异地”进行操作。这意味着对克隆不在 DOM 上的克隆进行操作。然后,用修改后的克隆对整个表进行一次替换。这样,运营就不会陷入困境。

Here's an answer 指的是几种“克隆” DOM 并为 DOM 之外的操作创建“容器元素”的方法。

【讨论】:

  • 我可能对 DOM 重绘假设过激了。创建一个克隆的 domNode 并使用它似乎并没有更快。似乎 IE 的 domNode 操作工具可能就是那么慢。
【解决方案3】:

您可以尝试将您的表格(表格 DOM 元素)从文档中分离出来,遍历它并像您一样删除空白文本节点,然后将表格重新插入到原始位置。从理论上讲,您应该提高速度 - 渲染树不需要在每次通过时更新,这对于文档中的表格来说代价高昂。

【讨论】:

  • 感谢您的建议,这就是我的想法/希望。然而,当我运行测试时,处理从 DOM 中移除的表实际上变得更慢了。这没有任何意义,但这就是我得到的结果。
猜你喜欢
  • 2023-03-08
  • 2014-06-10
  • 1970-01-01
  • 2011-06-12
  • 1970-01-01
  • 2021-05-30
  • 1970-01-01
  • 2017-09-14
  • 2015-03-26
相关资源
最近更新 更多