web-dev-qa-db-ja.com

JavaScriptでDOMノードのすべての子要素を削除する

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で回答を提供する場合は、さらに注意が必要です。

696
Polaris878

オプション1(もっと遅い。下記のコメントを参照)

var myNode = document.getElementById("foo");
myNode.innerHTML = '';

オプション2(はるかに高速):

var myNode = document.getElementById("foo");
while (myNode.firstChild) {
    myNode.removeChild(myNode.firstChild);
}
1379
Gabriel McAdams

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"として理解されることが多く、最初の反復だけが削除するノードを持っているので結果は意味がありません。投稿時にはこのスレッドに間違って設定されたテストがありました。

89
npjohns
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メソッドを使うだけでは、そのデータは残ります。

41
user113716

あなたがjQueryを使用する場合:

$('#foo').empty();

そうでなければ:

var foo = document.getElementById('foo');
while (foo.firstChild) foo.removeChild(foo.firstChild);
34
PleaseStand

removeで、最新のJavascriptを使用してください。

const parent = document.getElementById("foo");
while (parent.firstChild) {
    parent.firstChild.remove();
}

これは、ES5でノード削除を記述するための新しい方法です。それはVanilla JSであり、以前のバージョンよりも はるかに きれいです。

ほとんどのユーザーは最新のブラウザを使用する必要があります。または必要に応じて変換することもできます。

ブラウザのサポート - 93%4月2019

30
Gibolt

最速...

var removeChilds = function (node) {
    var last;
    while (last = node.lastChild) node.removeChild(last);
};

Andrey Lushnikovに感謝します。 jsperf.comへのリンク (クールなサイト!).

編集:明らかに、firstChildとlastChildの間でChromeにパフォーマンスの違いはありません。一番上の答えはパフォーマンスの良い解決策を示しています。

19
Gabe Halsmer

子を持たないノードだけを持ちたい場合は、次のようにコピーすることもできます。

var dupNode = document.getElementById("foo").cloneNode(false);

あなたが達成しようとしていることによります。

9
DanMan
element.textContent = '';

標準以外はinnerTextのようです。 removeChild()より やや遅い ですが、使用するのが簡単で、削除するものがそれほど多くない場合でも、パフォーマンスに大きな影響はありません。

6
bjb568

これは別のアプローチです:

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();
}
5
Nathan K

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 );

このメソッドは要素内の文字列を置換するときにとても便利だと思います。混乱をどうやって片付けるかを心配する代わりに、最初からやり直すのではなくノードに何が含まれるのかわからない場合.

4
jeroen

それを達成するためのオプションがいくつかあります。

最速 ():

while (node.lastChild) {
  node.removeChild(node.lastChild);
}

代替案(遅い):

while (node.firstChild) {
  node.removeChild(node.firstChild);
}

while (node.hasChildNodes()) {
  node.removeChild(node.lastChild);
}

推奨されるオプションを使用したベンチマーク

3
magiccrafter

私は人々がやっているのを見ました:

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によって行われます。

3
Noitidart
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
        }
    }
}

これにより、要素内のすべてのノードが削除されます。

3
Henrik

これが私の普段のやり方です。

HTMLElement.prototype.empty = function() {
    while (this.firstChild) {
        this.removeChild(this.firstChild);
    }
}

あとで、後でdom要素を空にすることもできます。

anyDom.empty()
2
Ado Ren

Javascriptを使ってノードの子ノードを削除する最も簡単な方法

var myNode = document.getElementById("foo");
while(myNode.hasChildNodes())
{
   myNode.removeChild(myNode.lastChild);
}
2
Chaitanya Bapat

innerTextが勝者です! http://jsperf.com/innerhtml-vs-removechild/133 。これまでのすべてのテストで、最初の反復で親ノードのinner domが削除され、次にinnerHTMLまたはremoveChildが空のdivに適用されていました。

2
Alexey

範囲ループを使用することは私にとって最も自然なことです。

for (var child of node.childNodes) {
    child.remove();
}

ChromeとFirefoxでの私の測定によると、それは約1.3倍遅くなります。通常の状況では、これはおそらく問題にはなりません。

2
emu

一般に、JavaScriptは配列を使用してDOMノードのリストを参照します。そのため、HTMLElements配列を使用してそれを行うことに関心がある場合、これはうまく機能します。また、注目に値するのは、JavaScriptプロトの代わりに配列参照を使用しているため、これはIEを含むすべてのブラウザで機能するはずです。

while(nodeArray.length !== 0) {
  nodeArray[0].parentNode.removeChild(nodeArray[0]);
}
1
r00t hkr

他の人がこの質問に言及しているのを見ただけで、まだ見ていない方法を追加することを考えました。

function clear(el) {
    el.parentNode.replaceChild(el.cloneNode(false), el);
}

var myNode = document.getElementById("foo");
clear(myNode);

Clear関数は要素を取り、それ自身を子ではなくコピーで置き換えるために親ノードを使うことです。要素がスパースである場合はパフォーマンスの向上はそれほど多くありませんが、要素に多数のノードがある場合はパフォーマンスの向上が実現されます。

0

私たちがここで最も簡単な方法をたどっていないのはなぜでしょうか。

const foo = document.querySelector(".foo");
while (foo.firstChild) {
  foo.firstChild.remove();     
}
  • 親divを選択する
  • Whileループ内で "remove"メソッドを使用して、最初の子要素がなくなるまで削除します。
0
NEelansh VErma