JavaScript Rimuovi elemento DOM


198

Sto cercando di verificare se esiste un elemento DOM e se esiste eliminarlo e se non esiste crearlo.

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

Verifica se esiste funziona, la creazione dell'elemento funziona, ma l'eliminazione dell'elemento non funziona. Fondamentalmente tutto questo codice fa è iniettare un iframe in una pagina Web facendo clic su un pulsante. Quello che vorrei che accadesse è se l'iframe è già lì per eliminarlo. Ma per qualche ragione sto fallendo.


Risposte:


339

removeChild dovrebbe essere invocato sul genitore, ovvero:

parent.removeChild(child);

Nel tuo esempio, dovresti fare qualcosa del tipo:

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

Grazie capito prima di leggere il tuo post. Ho dovuto cambiarlo in whereeto.removeChild (whereto.childNodes [0]);
Joshua Redfield,

6
Funzionerebbe anche supponendo che il tuo frame sia sempre il primo figlio del debugdiv. L'utilizzo parentNodeè una soluzione più generica che funziona con qualsiasi elemento.
Casablanca,

1
Questa soluzione potrebbe non essere sufficiente. Se qualcuno lo sta leggendo, dai un'occhiata al suggerimento di Glenn
Sebas,

79

Nella maggior parte dei browser, c'è un modo leggermente più conciso di rimuovere un elemento dal DOM che chiamare .removeChild(element)il suo genitore, che è semplicemente chiamare element.remove(). A tempo debito, questo probabilmente diventerà il modo standard e idiomatico di rimuovere un elemento dal DOM.

Il .remove()metodo è stato aggiunto al DOM Living Standard nel 2011 ( commit ) e da allora è stato implementato da Chrome, Firefox, Safari, Opera e Edge. Non era supportato in nessuna versione di Internet Explorer.

Se vuoi supportare i browser più vecchi, dovrai evitarlo. Questo risulta essere un po 'irritante, sia perché nessuno sembra aver creato uno shim DOM per tutti gli usi che contenga questi metodi, sia perché non stiamo semplicemente aggiungendo il metodo a un singolo prototipo; è un metodo di ChildNode, che è solo un'interfaccia definita dalle specifiche e non è accessibile a JavaScript, quindi non possiamo aggiungere nulla al suo prototipo. Quindi dobbiamo trovare tutti i prototipi che ereditano ChildNodee sono effettivamente definiti nel browser e aggiungerli .remove.

Ecco lo spessore che mi è venuto in mente, che ho confermato funziona in IE 8.

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

Questo non funzionerà in IE 7 o inferiore, da allora estensione di prototipi DOM non è possibile prima di IE 8 . Immagino, tuttavia, che sull'orlo del 2015 la maggior parte delle persone non debba preoccuparsi di queste cose.

Dopo averli inclusi shim, sarai in grado di rimuovere un elemento DOM elementdal DOM semplicemente chiamando

element.remove();

1
Lasciandolo qui: polyfill.io/v2/docs/features/#Element_prototype_remove se includi quel servizio di polyfill automagic riceverai supporto per IE 7.
complistic

4
Questo è sicuramente il modo di farlo nel 2017 purché non ti interessi di IE. Vedi: developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove
nevf

45

Sembra che non abbia abbastanza rappresentante per pubblicare un commento, quindi un'altra risposta dovrà fare.

Quando scolleghi un nodo usando removeChild () o impostando la proprietà innerHTML sul genitore, devi anche assicurarti che non ci sia nient'altro che lo faccia riferimento altrimenti non verrà effettivamente distrutto e causerà una perdita di memoria. Esistono molti modi in cui avresti potuto prendere un riferimento al nodo prima di chiamare removeChild () e devi assicurarti che quei riferimenti che non sono usciti dall'ambito vengano rimossi esplicitamente.

Doug Crockford scrive qui che i gestori di eventi sono noti come causa di riferimenti circolari in IE e suggerisce di rimuoverli in modo esplicito come segue prima di chiamare 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]);
        }
    }
}

E anche se prendi molte precauzioni puoi comunque ottenere perdite di memoria in IE come descritto da Jens-Ingo Farley qui .

E infine, non cadere nella trappola di pensare che l' eliminazione Javascript sia la risposta. Sembra essere suggerito da molti, ma non farà il lavoro. Qui è un grande riferimento sulla comprensione di eliminazione dalla Kangax.


1
forse puoi mostrare alcuni jsFiddle per provare questo. Grazie
Muhaimin,

1
Confermo questo comportamento. Il mio framework utilizza un albero di mappatura di oggetti Javascript sul layout dom. Ogni oggetto js fa riferimento al suo elemento dom. Anche se chiamo element.parentNode.removeChildper rimuovere elementi, rimangono vivi e possono ancora essere referenziati. Semplicemente non sono visibili nel normale albero dom.
Sebas,

Sì, e quindi la rimozione del puntatore globale a quell'oggetto di mappatura js sblocca magicamente il Garbage Collector. Questa è un'aggiunta importante alla risposta accettata.
Sebas,

11

Utilizzando Node.removeChild () fa il lavoro per te, usa semplicemente qualcosa del genere:

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

In DOM 4, è stato applicato il metodo di rimozione, ma esiste un supporto scarso del browser secondo W3C:

Il metodo node.remove () è implementato nella specifica DOM 4. Ma a causa del supporto scarso del browser, non dovresti usarlo.

Ma puoi usare il metodo remove se usi jQuery ...

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

Anche in nuovi framework come è possibile utilizzare le condizioni per rimuovere un elemento, ad esempio *ngIfin Angolare e in React, il rendering di viste diverse dipende dalle condizioni ...


1
Se stai creando un nodo modale in js usando createElement, assicurati solo di verificare se il nodo esiste prima di rimuoverlo. if (leftSection) {..your code} dovrebbe fare il lavoro.
Afsan Abdulali Gujarati,

0

Se sei felice di usare la brillante funzione:

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

Per eliminare completamente l'elemento dal DOM.

Per rimuovere gli elementi senza rimuovere dati ed eventi, utilizzare invece questo:

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

jQuery Docs

Il .remove()metodo estrae elementi dal DOM. Utilizzare .remove()quando si desidera rimuovere l'elemento stesso, nonché tutto ciò che contiene. Oltre agli elementi stessi, vengono rimossi tutti gli eventi associati e i dati jQuery associati agli elementi. Per rimuovere gli elementi senza rimuovere dati ed eventi, utilizzare .detach()invece.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.