Pol*_*878 782 javascript dom
我将如何在JavaScript中删除DOM节点的所有子元素?
说我有以下(丑陋的)HTML:
<p id="foo">
<span>hello</span>
<div>world</div>
</p>
Run Code Online (Sandbox Code Playgroud)
我抓住了我想要的节点:
var myNode = document.getElementById("foo");
Run Code Online (Sandbox Code Playgroud)
我该怎样才能删除foo刚<p id="foo"></p>离开的孩子?
我可以这样做:
myNode.childNodes = new Array();
Run Code Online (Sandbox Code Playgroud)
或者我应该使用某种组合removeElement?
我希望答案是直接的DOM; 如果您还提供jQuery中的答案以及仅限DOM的答案,那么可以提供额外的分数.
Gab*_*ams 1533
选项1(慢得多,见下面的评论):
doFoo.onclick = () => {
const myNode = document.getElementById("foo");
myNode.innerHTML = '';
}Run Code Online (Sandbox Code Playgroud)
选项2(快得多):
<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
<span>Hello</span>
</div>
<button id='doFoo'>Remove Via innerHTML</button>Run Code Online (Sandbox Code Playgroud)
npj*_*hns 101
目前接受的答案是关于innerHTML较慢(在IE和Chrome中至少)的错误,正如m93a正确提到的那样.
使用此方法可以大大加快Chrome和FF的速度(这会破坏附加的jquery数据):
var cNode = node.cloneNode(false);
node.parentNode.replaceChild(cNode, node);
Run Code Online (Sandbox Code Playgroud)
在FF和Chrome的遥远的第二,在IE中最快:
node.innerHTML = '';
Run Code Online (Sandbox Code Playgroud)
InnerHTML 不会破坏你的事件处理程序或破坏jquery引用,它也建议作为解决方案:https: //developer.mozilla.org/en-US/docs/Web/API/Element.innerHTML
最快的DOM操作方法(仍比前两个慢)是Range删除,但IE9之前不支持范围.
var range = document.createRange();
range.selectNodeContents(node);
range.deleteContents();
Run Code Online (Sandbox Code Playgroud)
提到的其他方法似乎具有可比性,但比innerHTML慢很多,除了异常值,jquery(1.1.1和3.1.1),它比其他任何方法慢得多:
$(node).empty();
Run Code Online (Sandbox Code Playgroud)
证据在这里:
http://jsperf.com/innerhtml-vs-removechild/167 http://jsperf.com/innerhtml-vs-removechild/300
https://jsperf.com/remove-all-child-elements-of-a- dom-node-in-javascript
(jsperf重启的新url,因为编辑旧的url不起作用)
Jsperf的"per-test-loop"通常被理解为"per-iteration",只有第一次迭代才有删除的节点,因此结果毫无意义,在发布时,此线程中的测试设置不正确.
Mas*_*eed 67
replaceChildren()API!现在可以使用(跨浏览器支持)replaceChildrenAPI替换所有子项:
container.replaceChildren(...arrayOfNewChildren);
Run Code Online (Sandbox Code Playgroud)
这将同时做到:
您还可以使用相同的 API 来删除现有的子项,而不替换它们:
container.replaceChildren();
Run Code Online (Sandbox Code Playgroud)
Chrome/Edge 86+、Firefox 78+ 和 Safari 14+ 完全支持此功能。这是完全指定的行为。这可能比这里提出的任何其他方法都快,因为删除旧孩子和添加新孩子不需要innerHTML,并且一步而不是多个。
Gib*_*olt 50
remove!const parent = document.getElementById("foo");
while (parent.firstChild) {
parent.firstChild.remove();
}
Run Code Online (Sandbox Code Playgroud)
这是在ES5中编写节点删除的更新方法.它是vanilla JS,读起来比以前的版本好多了.
大多数用户应该使用现代浏览器,或者您可以根据需要进行调整.
浏览器支持 - 2018年4月91%
use*_*716 43
var myNode = document.getElementById("foo");
var fc = myNode.firstChild;
while( fc ) {
myNode.removeChild( fc );
fc = myNode.firstChild;
}
Run Code Online (Sandbox Code Playgroud)
如果你有可能有jQuery受影响的后代,那么你必须使用一些方法来清理jQuery数据.
$('#foo').empty();
Run Code Online (Sandbox Code Playgroud)
jQuery .empty()方法将确保清除与要删除的元素相关联的jQuery的任何数据.
如果您只是使用DOM删除子项的方法,那么该数据将保留.
Ple*_*and 35
如果你使用jQuery:
$('#foo').empty();
Run Code Online (Sandbox Code Playgroud)
如果你不这样做:
var foo = document.getElementById('foo');
while (foo.firstChild) foo.removeChild(foo.firstChild);
Run Code Online (Sandbox Code Playgroud)
Gab*_*mer 20
最快的...
var removeChilds = function (node) {
var last;
while (last = node.lastChild) node.removeChild(last);
};
Run Code Online (Sandbox Code Playgroud)
感谢Andrey Lushnikov与jsperf.com(酷网站!)的链接.
编辑:要清楚,在firstChild和lastChild之间Chrome没有性能差异.最佳答案显示了良好的性能解决方案.
如果您只想让节点没有子节点,您也可以像这样复制它:
var dupNode = document.getElementById("foo").cloneNode(false);
Run Code Online (Sandbox Code Playgroud)
取决于你想要实现的目标.
myNode.querySelectorAll(\'*\').forEach( n => n.remove() );\nRun Code Online (Sandbox Code Playgroud)\n这回答了问题,并删除 \xe2\x80\x9call 子节点\xe2\x80\x9d。
\n如果存在属于myNode它们的文本节点,则可以使用 CSS 选择器选择\xe2\x80\x99,在这种情况下,我们\xe2\x80\x99ve 也可以应用:
myNode.textContent = \'\';\nRun Code Online (Sandbox Code Playgroud)\n实际上,最后一种可能是最快、更有效/高效的解决方案。
\n.textContent.innerText比和更高效.innerHTML,请参阅:MDN
一个单行代码,用于迭代地node从 DOM 中删除 a 的所有子级
Array.from(node.children).forEach(c => c.remove())
Run Code Online (Sandbox Code Playgroud)
或者
[...node.children].forEach(c => c.remove())
Run Code Online (Sandbox Code Playgroud)
我审查了所有问题并决定测试最关键测试用例的性能:
\n所以我的 HTML:
\n<div id="target">\n <div><p>Title</p></div>\n <!-- 1000 at all -->\n <div><p>Title</p></div>\n</div>\nRun Code Online (Sandbox Code Playgroud)\n// innerHTML\ntarget.innerHTML = "";\nRun Code Online (Sandbox Code Playgroud)\n// lastChild\nwhile (target.hasChildNodes()) {\n target.removeChild(target.lastChild);\n}\nRun Code Online (Sandbox Code Playgroud)\n// firstChild\nwhile (target.hasChildNodes()) {\n target.removeChild(target.firstChild);\n}\nRun Code Online (Sandbox Code Playgroud)\n// replaceChildren\ntarget.replaceChildren();\nRun Code Online (Sandbox Code Playgroud)\nChecked test: innerHTML x 1,222,273 ops/sec \xc2\xb10.47% (63 runs sampled)\nChecked test: lastChild x 1,336,734 ops/sec \xc2\xb10.87% (65 runs sampled)\nChecked test: firstChild x 1,313,521 ops/sec \xc2\xb10.74% (64 runs sampled)\nChecked test: replaceChildren x 743,076 ops/sec \xc2\xb11.08% (53 runs sampled)\n\nChecked test: innerHTML x 1,202,727 ops/sec \xc2\xb10.83% (63 runs sampled)\nChecked test: lastChild x 1,360,350 ops/sec \xc2\xb10.72% (65 runs sampled)\nChecked test: firstChild x 1,348,498 ops/sec \xc2\xb10.78% (63 runs sampled)\nChecked test: replaceChildren x 743,076 ops/sec \xc2\xb10.86% (53 runs sampled)\n\nChecked test: innerHTML x 1,191,838 ops/sec \xc2\xb10.73% (62 runs sampled)\nChecked test: lastChild x 1,352,657 ops/sec \xc2\xb11.42% (63 runs sampled)\nChecked test: firstChild x 1,327,664 ops/sec \xc2\xb11.27% (65 runs sampled)\nChecked test: replaceChildren x 754,166 ops/sec \xc2\xb11.88% (61 runs sampled)\nRun Code Online (Sandbox Code Playgroud)\n现代 API 最慢。第一个孩子和最后一个孩子的方式是相等的,如果比较多个情况,可能会出现一些副作用。但你可以并排看到:
\nChecked test: firstChild x 1,423,497 ops/sec \xc2\xb10.53% (63 runs sampled)\nChecked test: lastChild x 1,422,560 ops/sec \xc2\xb10.36% (66 runs sampled)\n\nChecked test: firstChild x 1,368,175 ops/sec \xc2\xb10.57% (65 runs sampled)\nChecked test: lastChild x 1,381,759 ops/sec \xc2\xb10.39% (66 runs sampled)\n\nChecked test: firstChild x 1,372,109 ops/sec \xc2\xb10.37% (66 runs sampled)\nChecked test: lastChild x 1,355,811 ops/sec \xc2\xb10.35% (65 runs sampled)\nRun Code Online (Sandbox Code Playgroud)\nChecked test: lastChild x 1,364,830 ops/sec \xc2\xb10.65% (64 runs sampled)\nChecked test: firstChild x 1,365,617 ops/sec \xc2\xb10.41% (65 runs sampled)\n\nChecked test: lastChild x 1,389,458 ops/sec \xc2\xb10.50% (63 runs sampled)\nChecked test: firstChild x 1,387,861 ops/sec \xc2\xb10.40% (64 runs sampled)\n\nChecked test: lastChild x 1,388,208 ops/sec \xc2\xb10.43% (65 runs sampled)\nChecked test: firstChild x 1,413,741 ops/sec \xc2\xb10.47% (65 runs sampled)\nRun Code Online (Sandbox Code Playgroud)\nPS浏览器:火狐111.0.1
\nelement.textContent = '';
Run Code Online (Sandbox Code Playgroud)
它就像innerText,标准除外.这是慢一点比removeChild(),但它更容易使用,不会有太大的性能差异的,如果你没有太多的东西可删除.
回应 DanMan、Maarten 和 Matt。在我的结果中,克隆节点来设置文本确实是一种可行的方法。
// @param {node} node
// @return {node} empty node
function removeAllChildrenFromNode (node) {
var shell;
// do not copy the contents
shell = node.cloneNode(false);
if (node.parentNode) {
node.parentNode.replaceChild(shell, node);
}
return shell;
}
// use as such
var myNode = document.getElementById('foo');
myNode = removeAllChildrenFromNode( myNode );
Run Code Online (Sandbox Code Playgroud)
这也适用于不在 dom 中的节点,当尝试访问父节点时返回 null。此外,如果您需要安全,在添加内容之前节点为空,这非常有帮助。考虑下面的用例。
// @param {node} node
// @param {string|html} content
// @return {node} node with content only
function refreshContent (node, content) {
var shell;
// do not copy the contents
shell = node.cloneNode(false);
// use innerHTML or you preffered method
// depending on what you need
shell.innerHTML( content );
if (node.parentNode) {
node.parentNode.replaceChild(shell, node);
}
return shell;
}
// use as such
var myNode = document.getElementById('foo');
myNode = refreshContent( myNode );
Run Code Online (Sandbox Code Playgroud)
我发现这个方法在替换元素内的字符串时非常有用,如果您不确定节点将包含什么,而不是担心如何清理混乱,而是重新开始。
这是另一种方法:
function removeAllChildren(theParent){
// Create the Range object
var rangeObj = new Range();
// Select all of theParent's children
rangeObj.selectNodeContents(theParent);
// Delete everything that is selected
rangeObj.deleteContents();
}
Run Code Online (Sandbox Code Playgroud)
这是我通常做的:
HTMLElement.prototype.empty = function() {
while (this.firstChild) {
this.removeChild(this.firstChild);
}
}
Run Code Online (Sandbox Code Playgroud)
瞧,稍后您可以使用以下命令清空任何 dom 元素:
anyDom.empty()
Run Code Online (Sandbox Code Playgroud)
使用范围循环对我来说感觉最自然:
for (var child of node.childNodes) {
child.remove();
}
Run Code Online (Sandbox Code Playgroud)
根据我在 Chrome 和 Firefox 中的测量,速度大约慢 1.3 倍。在正常情况下,这也许并不重要。
| 归档时间: |
|
| 查看次数: |
762260 次 |
| 最近记录: |