JavaScript DOM削除要素


198

DOM要素が存在するかどうかをテストし、存在する場合は削除し、存在しない場合は作成します。

var duskdawnkey = localStorage["duskdawnkey"];
var iframe = document.createElement("iframe");
var whereto = document.getElementById("debug");
var frameid = document.getElementById("injected_frame");
iframe.setAttribute("id", "injected_frame");
iframe.setAttribute("src", 'http://google.com');
iframe.setAttribute("width", "100%");
iframe.setAttribute("height", "400");

if (frameid) // check and see if iframe is already on page
{ //yes? Remove iframe
    iframe.removeChild(frameid.childNodes[0]);
} else // no? Inject iframe
{
    whereto.appendChild(iframe);
    // add the newly created element and it's content into the DOM
    my_div = document.getElementById("debug");
    document.body.insertBefore(iframe, my_div);
}

存在するかどうかのチェックは機能し、要素の作成は機能しますが、要素の削除は機能しません。基本的に、このコードが行うことは、ボタンをクリックするだけでiframeをWebページに挿入することです。削除したいiframeがすでに存在する場合、私が実行したいことです。しかし、何らかの理由で失敗しています。


回答:


338

removeChild 親で呼び出す必要があります。つまり、

parent.removeChild(child);

あなたの例では、あなたは次のようなことをしているはずです:

if (frameid) {
    frameid.parentNode.removeChild(frameid);
}

私があなたの投稿を読む直前にそれを理解してくれてありがとう。これをwhereto.removeChild(whereto.childNodes [0]);に変更する必要がありました。
ジョシュアレッドフィールド

6
これは、フレームが常にdebugdivの最初の子であると仮定しても機能します。を使用するparentNodeと、あらゆる要素で機能するより一般的なソリューションになります。
カサブランカ

1
このソリューションでは不十分な場合があります。誰かがこれを読んでいるなら、グレンの提案を見てください
Sebas

79

ほとんどのブラウザでは、DOMから要素を削除する方法として.removeChild(element)、親を呼び出すよりも少し簡潔な方法がありますelement.remove()。つまり、を呼び出すだけです。やがて、これはおそらくDOMから要素を削除する標準的で慣用的な方法になるでしょう。

この.remove()メソッドは2011年にDOM Living Standardに追加され(commit)、それ以降、Chrome、Firefox、Safari、Opera、およびEdgeによって実装されました。Internet Explorerのどのバージョンでもサポートされていませんでした。

古いブラウザをサポートしたい場合は、それをシムする必要があります。これらのメソッドを含む汎用のDOMシムを誰も作成していないようであり、単一のプロトタイプにメソッドを追加するだけではないため、これは少し苛立たしいことがわかります。これはのメソッドでありChildNode、仕様で定義されたインターフェースであり、JavaScriptにはアクセスできないため、プロトタイプに何も追加できません。したがってChildNode、ブラウザから継承され、実際にブラウザで定義されているすべてのプロトタイプを見つけて、.removeそれらに追加する必要があります。

これが私が思いついたシムです。IE8で動作を確認しました。

(function () {
    var typesToPatch = ['DocumentType', 'Element', 'CharacterData'],
        remove = function () {
            // The check here seems pointless, since we're not adding this
            // method to the prototypes of any any elements that CAN be the
            // root of the DOM. However, it's required by spec (see point 1 of
            // https://dom.spec.whatwg.org/#dom-childnode-remove) and would
            // theoretically make a difference if somebody .apply()ed this
            // method to the DOM's root node, so let's roll with it.
            if (this.parentNode != null) {
                this.parentNode.removeChild(this);
            }
        };

    for (var i=0; i<typesToPatch.length; i++) {
        var type = typesToPatch[i];
        if (window[type] && !window[type].prototype.remove) {
            window[type].prototype.remove = remove;
        }
    }
})();

IE 8以前ではDOMプロトタイプを拡張できないため、これはIE 7以下では機能しません。しかし、私は、2015年が近づくと、ほとんどの人はそのようなことを気にする必要がないと考えています。

それらをシムに含めたら、次のようにelement呼び出すだけで、DOMからDOM要素を削除できます。

element.remove();

1
これをここに残すだけです:polyfill.io/v2/docs/features/#Element_prototype_removeそのautomagicポリフィルサービスを含めると、IE 7にサポートが返されます
complistic

4
IEを気にしない限り、これは間違いなく2017年にそれを行う方法です。参照:developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove
nevf

45

コメントを投稿するのに十分な担当者がいないようですので、別の回答を行う必要があります。

removeChild()を使用して、または親のinnerHTMLプロパティを設定してノードのリンクを解除する場合は、ノードを参照しているノードが他にないことを確認する必要があります。そうしないと、実際に破棄されず、メモリリークが発生します。removeChild()を呼び出す前にノードへの参照を取得する方法はたくさんあり、スコープ外に出ていない参照が明示的に削除されていることを確認する必要があります。

Doug Crockfordはここで、イベントハンドラーがIEでの循環参照の原因として知られていることを記述し、removeChild()を呼び出す前に、次のように明示的に削除することを推奨しています。

function purge(d) {
    var a = d.attributes, i, l, n;
    if (a) {
        for (i = a.length - 1; i >= 0; i -= 1) {
            n = a[i].name;
            if (typeof d[n] === 'function') {
                d[n] = null;
            }
        }
    }
    a = d.childNodes;
    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            purge(d.childNodes[i]);
        }
    }
}

そして、多くの予防策を講じたとしても、ここで Jens-Ingo Farleyによって説明されているように、IEでメモリリークが発生する可能性があります

そして最後に、Javascriptの削除が答えであると考える罠に陥らないでください。それは多くの人から提案されているようですが、仕事をしません。ここで理解した上で偉大なリファレンスです削除 Kangaxでは。


1
おそらく、これを証明するためにいくつかのjsFiddleを表示できます。ありがとう
Muhaimin

1
私はこの行動を確認します。私のフレームワークは、domレイアウト上でJavascriptオブジェクトマッピングツリーを使用しています。各jsオブジェクトは、そのdom要素を参照します。element.parentNode.removeChild要素を削除するように呼び出しても、それらは生きたままであり、参照される可能性があります。それらは通常のdomツリーには表示されません。
セバス

はい、そのjsマッピングオブジェクトへのグローバルポインターを削除すると、ガベージコレクターが魔法のようにロック解除されます。これは、受け入れられた回答への重要な追加です。
セバス2015

11

Node.removeChild()を使用すると、あなたのために仕事をします、単に次のようなものを使用してください:

var leftSection = document.getElementById('left-section');
leftSection.parentNode.removeChild(leftSection);

DOM 4では、removeメソッドが適用されましたが、W3Cによると、ブラウザのサポートは不十分です。

node.remove()メソッドは、DOM 4仕様で実装されています。ただし、ブラウザのサポートが不十分なため、使用しないでください。

しかし、jQueryを使用している場合は、removeメソッドを使用できます...

$('#left-section').remove(); //using remove method in jQuery

また、条件を使用して要素を削除できるような新しいフレームワーク*ngIfでは、AngularやReactなどで、さまざまなビューのレンダリングが条件に依存します...


createElementを使用してjsでモーダルノードを作成する場合は、削除する前にノードが存在するかどうかを確認してください。 if(leftSection){..your code}がその仕事をするはずです。
Afsan Abdulali Gujarati

0

見事な機能を使用してよろしければ:

$("#foo").remove();

DOMから要素を完全に削除します。

データとイベントを削除せずに要素を削除するには、代わりにこれを使用します:

$("#foo").detach();

jQueryドキュメント

この.remove()メソッドは、DOMから要素を取り出します。.remove()要素自体だけでなく、要素内のすべてを削除する場合に使用します。要素自体に加えて、要素に関連付けられたすべてのバインドされたイベントとjQueryデータが削除されます。データとイベントを削除せずに要素を削除するには、.detach()代わりにを使用します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.