Élément JavaScript DOM remove

198

J'essaie de tester si un élément DOM existe, et s'il existe, supprimez-le et s'il n'existe pas, créez-le.

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

Vérifier s'il existe fonctionne, créer l'élément fonctionne, mais pas supprimer l'élément. Fondamentalement, tout ce code ne fait qu'injecter une iframe dans une page Web en cliquant sur un bouton. Ce que j'aimerais, c'est que l'iframe soit déjà là pour le supprimer. Mais pour une raison quelconque, j'échoue.

Joshua Redfield
la source

Réponses:

339

removeChild doit être invoqué sur le parent, c'est-à-dire:

parent.removeChild(child);

Dans votre exemple, vous devriez faire quelque chose comme:

if (frameid) {
    frameid.parentNode.removeChild(frameid);
}
casablanca
la source
Merci de l'avoir compris juste avant de lire votre message. J'ai dû le remplacer par whereeto.removeChild (whereeto.childNodes [0]);
Joshua Redfield
6
Cela fonctionnerait également en supposant que votre cadre est toujours le premier enfant du debugdiv. L'utilisation parentNodeest une solution plus générique qui fonctionnera avec n'importe quel élément.
casablanca
1
Cette solution pourrait ne pas suffire. Si quelqu'un lit ceci, veuillez jeter un œil à la suggestion de Glenn
Sebas
79

Dans la plupart des navigateurs, il existe un moyen un peu plus succinct de supprimer un élément du DOM que d'appeler .removeChild(element)son parent, qui consiste simplement à appeler element.remove(). En temps voulu, cela deviendra probablement le moyen standard et idiomatique de supprimer un élément du DOM.

La .remove()méthode a été ajoutée au DOM Living Standard en 2011 ( validation ) et a depuis été mise en œuvre par Chrome, Firefox, Safari, Opera et Edge. Il n'était pris en charge dans aucune version d'Internet Explorer.

Si vous souhaitez prendre en charge les anciens navigateurs, vous devrez le caler. Cela s'avère un peu irritant, à la fois parce que personne ne semble avoir créé un shim DOM polyvalent contenant ces méthodes, et parce que nous ne sommes pas en train d'ajouter la méthode à un seul prototype; c'est une méthode de ChildNode, qui n'est qu'une interface définie par la spécification et qui n'est pas accessible à JavaScript, nous ne pouvons donc rien ajouter à son prototype. Nous devons donc trouver tous les prototypes qui héritent ChildNodeet sont réellement définis dans le navigateur, et y ajouter .remove.

Voici le shim que j'ai trouvé, dont j'ai confirmé le fonctionnement dans 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;
        }
    }
})();

Cela ne fonctionnera pas dans IE 7 ou inférieur, car l' extension des prototypes DOM n'est pas possible avant IE 8 . Je pense, cependant, qu'à la veille de 2015, la plupart des gens n'ont pas à se soucier de telles choses.

Une fois que vous les aurez inclus, vous pourrez supprimer un élément DOM elementdu DOM en appelant simplement

element.remove();
Mark Amery
la source
1
Juste en laissant ceci ici: polyfill.io/v2/docs/features/#Element_prototype_remove si vous incluez ce service de polyfill automagique, vous obtiendrez un support pour IE 7.
compliste
4
C'est certainement la façon de le faire en 2017 tant que vous ne vous souciez pas d'IE. Voir: developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove
nevf
45

Il semble que je n'ai pas assez de représentants pour poster un commentaire, donc une autre réponse devra faire.

Lorsque vous dissociez un nœud à l'aide de removeChild () ou en définissant la propriété innerHTML sur le parent, vous devez également vous assurer qu'il n'y a rien d'autre le référençant sinon il ne sera pas réellement détruit et entraînera une fuite de mémoire. Il existe de nombreuses façons dont vous auriez pu prendre une référence au nœud avant d'appeler removeChild () et vous devez vous assurer que les références qui ne sont pas sorties de la portée sont explicitement supprimées.

Doug Crockford écrit ici que les gestionnaires d'événements sont connus comme une cause des références circulaires dans IE et suggère de les supprimer explicitement comme suit avant d'appeler 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]);
        }
    }
}

Et même si vous prenez beaucoup de précautions, vous pouvez toujours obtenir des fuites de mémoire dans IE comme décrit par Jens-Ingo Farley ici .

Et enfin, ne tombez pas dans le piège de penser que la suppression de Javascript est la réponse. Cela semble être suggéré par beaucoup, mais ne fera pas l'affaire. Voici une grande référence sur la compréhension de la suppression par Kangax.

Glenn Lawrence
la source
1
vous pouvez peut-être montrer quelques jsFiddle pour le prouver. Merci
Muhaimin
1
Je confirme ce comportement. Mon framework utilise une arborescence de mappage d'objets Javascript sur la disposition dom. Chaque objet js référence son élément dom. Même si j'appelle element.parentNode.removeChildpour supprimer des éléments, ils restent en vie et peuvent toujours être référencés. Ils ne sont tout simplement pas visibles dans l'arbre dom ordinaire.
Sebas
Oui, puis la suppression du pointeur global sur cet objet de mappage js déverrouille comme par magie le garbage collector. Il s'agit d'un ajout important à la réponse acceptée.
Sebas
11

L'utilisation de Node.removeChild () fait le travail pour vous, utilisez simplement quelque chose comme ceci:

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

Dans DOM 4, la méthode de suppression est appliquée, mais la prise en charge du navigateur est médiocre selon le W3C:

La méthode node.remove () est implémentée dans la spécification DOM 4. Mais en raison de la mauvaise prise en charge du navigateur, vous ne devez pas l'utiliser.

Mais vous pouvez utiliser la méthode remove si vous utilisez jQuery ...

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

Dans de nouveaux cadres comme vous pouvez également utiliser des conditions pour supprimer un élément, par exemple *ngIfdans Angular et dans React, le rendu de vues différentes, dépend des conditions ...

Alireza
la source
1
Si vous créez un nœud modal dans js à l'aide de createElement, assurez-vous simplement de vérifier si le nœud existe avant de le supprimer. if (leftSection) {..votre code} devrait faire le travail.
Afsan Abdulali Gujarati
0

Si vous êtes heureux d'utiliser la fonction brillante:

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

Pour supprimer complètement l'élément du DOM.

Pour supprimer les éléments sans supprimer les données et les événements, utilisez plutôt ceci:

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

jQuery Docs

La .remove()méthode retire des éléments du DOM. À utiliser .remove()lorsque vous souhaitez supprimer l'élément lui-même, ainsi que tout ce qu'il contient. En plus des éléments eux-mêmes, tous les événements liés et les données jQuery associés aux éléments sont supprimés. Pour supprimer les éléments sans supprimer les données et les événements, utilisez .detach()plutôt.

Aryan Beezadhur
la source