JavaScriptでDOMノードのすべての子要素を削除する方法を教えてください。
次のような(見苦しい)HTMLがあるとします。
<p id="foo">
<span>hello</span>
<div>world</div>
</p>
そして欲しいノードをつかみます:
var myNode = document.getElementById("foo");
foo
の子を削除して<p id="foo"></p>
だけが残るようにするにはどうすればよいですか。
私はただできますか:
myNode.childNodes = new Array();
それともremoveElement
の組み合わせを使うべきですか?
私はその答えにDOMをまっすぐにして欲しいのですが。 DOMのみの回答と一緒にjQueryで回答を提供する場合は、さらに注意が必要です。
オプション1(もっと遅い。下記のコメントを参照)
var myNode = document.getElementById("foo");
myNode.innerHTML = '';
オプション2(はるかに高速):
var myNode = document.getElementById("foo");
while (myNode.firstChild) {
myNode.removeChild(myNode.firstChild);
}
M93aが正しく言及しているように、現在受け入れられている答えはinnerHTMLが遅くなること(少なくともIEとChrome)に関して間違っています。
ChromeとFFはこの方法を使うと劇的に速くなります(これは添付されたjqueryデータを破壊します):
var cNode = node.cloneNode(false);
node.parentNode.replaceChild(cNode ,node);
fFとChromeの場合は1秒以内、IEの場合は最速です。
node.innerHTML = '';
InnerHTML あなたのイベントハンドラを破壊したりjqueryの参照を壊したりしない 、ここでも解決策として推奨される: https://developer.mozilla.org/en-US/docs/Web/API/Element .innerHTML
最速のDOM操作方法(前の2つよりまだ遅い)はRangeの削除ですが、範囲はIE9までサポートされません。
var range = document.createRange();
range.selectNodeContents(node);
range.deleteContents();
言及された他の方法は同等であるように思われますが、他のものよりかなり遅い異常値jquery(1.1.1と3.1.1)を除いて、innerHTMLよりずっと遅いです:
$(node).empty();
ここに証拠:
http://jsperf.com/innerhtml-vs-removechild/167http://jsperf.com/innerhtml-vs-removechild/300 https://jsperf.com/remove-all-child-elements-of-a-dom-node-in-javascript (古いURLを編集しても機能しないため、jsperfを再起動するための新しいURL)
Jsperfの "per-test-loop"は "per-iteration"として理解されることが多く、最初の反復だけが削除するノードを持っているので結果は意味がありません。投稿時にはこのスレッドに間違って設定されたテストがありました。
var myNode = document.getElementById("foo");
var fc = myNode.firstChild;
while( fc ) {
myNode.removeChild( fc );
fc = myNode.firstChild;
}
JQueryが子孫に影響を与える可能性がある場合は、 must を使用してjQueryデータをクリーンアップします。
$('#foo').empty();
jQueryの.empty()
メソッド は、削除される要素に関連するすべてのデータを確実にクリーンアップします。
単に子を削除するためにDOM
メソッドを使うだけでは、そのデータは残ります。
あなたがjQueryを使用する場合:
$('#foo').empty();
そうでなければ:
var foo = document.getElementById('foo');
while (foo.firstChild) foo.removeChild(foo.firstChild);
remove
で、最新のJavascriptを使用してください。const parent = document.getElementById("foo");
while (parent.firstChild) {
parent.firstChild.remove();
}
これは、ES5でノード削除を記述するための新しい方法です。それはVanilla JSであり、以前のバージョンよりも はるかに きれいです。
ほとんどのユーザーは最新のブラウザを使用する必要があります。または必要に応じて変換することもできます。
ブラウザのサポート - 93%4月2019
最速...
var removeChilds = function (node) {
var last;
while (last = node.lastChild) node.removeChild(last);
};
Andrey Lushnikovに感謝します。 jsperf.comへのリンク (クールなサイト!).
編集:明らかに、firstChildとlastChildの間でChromeにパフォーマンスの違いはありません。一番上の答えはパフォーマンスの良い解決策を示しています。
子を持たないノードだけを持ちたい場合は、次のようにコピーすることもできます。
var dupNode = document.getElementById("foo").cloneNode(false);
あなたが達成しようとしていることによります。
element.textContent = '';
標準以外はinnerTextのようです。 removeChild()
より やや遅い ですが、使用するのが簡単で、削除するものがそれほど多くない場合でも、パフォーマンスに大きな影響はありません。
これは別のアプローチです:
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();
}
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 );
また、これは、parentNodeにアクセスしようとしたときにnullを返すDOM内にないノードに対しても機能します。さらに、安全を期する必要がある場合は、コンテンツを追加する前にノードを空にしておくと非常に便利です。下のユースケースを考えてください。
// @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 );
このメソッドは要素内の文字列を置換するときにとても便利だと思います。混乱をどうやって片付けるかを心配する代わりに、最初からやり直すのではなくノードに何が含まれるのかわからない場合.
それを達成するためのオプションがいくつかあります。
最速 ():
while (node.lastChild) {
node.removeChild(node.lastChild);
}
代替案(遅い):
while (node.firstChild) {
node.removeChild(node.firstChild);
}
while (node.hasChildNodes()) {
node.removeChild(node.lastChild);
}
私は人々がやっているのを見ました:
while (el.firstNode) {
el.removeChild(el.firstNode);
}
それなら誰かがel.lastNode
を使うほうが速いと言いました
しかし、私はこれが最速だと思います。
var children = el.childNodes;
for (var i=children.length - 1; i>-1; i--) {
el.removeNode(children[i]);
}
どう思いますか?
ps:このトピックは私にとって命の恩人でした。私のFirefoxのアドオンは私がinnerHTMLを使用してcuzを拒否されました。それは長い間習慣でした。それから私はこれに気を配った。そして私は実際に速度差に気づいた。読み込み時にinnerhtmlの更新には少し時間がかかりましたが、その瞬間はaddElementによって行われます。
var empty_element = function (element) {
var node = element;
while (element.hasChildNodes()) { // selected elem has children
if (node.hasChildNodes()) { // current node has children
node = node.lastChild; // set current node to child
}
else { // last child found
console.log(node.nodeName);
node = node.parentNode; // set node to parent
node.removeChild(node.lastChild); // remove last node
}
}
}
これにより、要素内のすべてのノードが削除されます。
これが私の普段のやり方です。
HTMLElement.prototype.empty = function() {
while (this.firstChild) {
this.removeChild(this.firstChild);
}
}
あとで、後でdom要素を空にすることもできます。
anyDom.empty()
Javascriptを使ってノードの子ノードを削除する最も簡単な方法
var myNode = document.getElementById("foo");
while(myNode.hasChildNodes())
{
myNode.removeChild(myNode.lastChild);
}
innerTextが勝者です! http://jsperf.com/innerhtml-vs-removechild/133 。これまでのすべてのテストで、最初の反復で親ノードのinner domが削除され、次にinnerHTMLまたはremoveChildが空のdivに適用されていました。
範囲ループを使用することは私にとって最も自然なことです。
for (var child of node.childNodes) {
child.remove();
}
ChromeとFirefoxでの私の測定によると、それは約1.3倍遅くなります。通常の状況では、これはおそらく問題にはなりません。
一般に、JavaScriptは配列を使用してDOMノードのリストを参照します。そのため、HTMLElements配列を使用してそれを行うことに関心がある場合、これはうまく機能します。また、注目に値するのは、JavaScriptプロトの代わりに配列参照を使用しているため、これはIEを含むすべてのブラウザで機能するはずです。
while(nodeArray.length !== 0) {
nodeArray[0].parentNode.removeChild(nodeArray[0]);
}
他の人がこの質問に言及しているのを見ただけで、まだ見ていない方法を追加することを考えました。
function clear(el) {
el.parentNode.replaceChild(el.cloneNode(false), el);
}
var myNode = document.getElementById("foo");
clear(myNode);
Clear関数は要素を取り、それ自身を子ではなくコピーで置き換えるために親ノードを使うことです。要素がスパースである場合はパフォーマンスの向上はそれほど多くありませんが、要素に多数のノードがある場合はパフォーマンスの向上が実現されます。
私たちがここで最も簡単な方法をたどっていないのはなぜでしょうか。
const foo = document.querySelector(".foo");
while (foo.firstChild) {
foo.firstChild.remove();
}