212 votes

JavaScript DOM supprimer élément

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

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

La vérification de l'existence de l'élément fonctionne, la création de l'élément fonctionne, mais la suppression de l'élément ne fonctionne pas. En gros, tout ce que fait ce code est d'injecter un iframe dans une page Web en cliquant sur un bouton. Ce que je voudrais, c'est que si la iframe est déjà là, elle soit supprimée. Mais pour une raison quelconque, je n'y arrive pas.

0 votes

350voto

casablanca Points 41814

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

parent.removeChild(child);

Dans votre exemple, vous devriez faire quelque chose comme :

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

0 votes

Merci, j'ai compris juste avant de lire ton message. J'ai dû le changer en whereto.removeChild(whereto.childNodes[0]) ;

6 votes

Cela fonctionnerait également en supposant que votre cadre est toujours le premier enfant de l'élément debug div. Utilisation de parentNode est une solution plus générique qui fonctionnera avec n'importe quel élément.

1 votes

Cette solution pourrait ne pas être suffisante. Si quelqu'un lit ces lignes, jetez un coup d'œil à la suggestion de Glenn.

91voto

Mark Amery Points 4705

Dans la plupart des navigateurs, il existe une manière un peu plus succincte de supprimer un élément du DOM que d'appeler .removeChild(element) sur son parent, ce qui revient à appeler element.remove() . En temps voulu, cela deviendra probablement la manière standard et idiomatique de supprimer un élément du DOM.

El .remove() a été ajoutée au niveau de vie des DOM en 2011 ( commettre ), et a depuis été implémenté par Chrome, Firefox, Safari, Opera, et Edge. Elle n'était prise en charge par aucune version d'Internet Explorer.

Si vous souhaitez prendre en charge des navigateurs plus anciens, vous devrez le modifier. Cela s'avère être un peu irritant, à la fois parce que personne ne semble avoir fait un DOM shim universel qui contienne ces méthodes, et parce que nous ne faisons pas qu'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 n'est pas accessible à JavaScript, nous ne pouvons donc rien ajouter à son prototype. Nous devons donc trouver tous les prototypes qui héritent de ChildNode et sont en réalité définis dans le navigateur, et ajoutent .remove à eux.

Voici la cale que j'ai mise au point et qui, je l'ai confirmé, fonctionne 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'à l'aube de 2015, la plupart des gens n'ont pas besoin de se soucier de ce genre de choses.

Une fois que vous avez inclus les cales, vous pourrez retirer un élément DOM element à partir du DOM en appelant simplement

element.remove();

47voto

Glenn Lawrence Points 376

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

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 que rien d'autre ne le référence, sinon il ne sera pas réellement détruit et cela entraînera une fuite de mémoire. Il existe de nombreuses façons de 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 leur portée sont explicitement supprimées.

Doug Crockford écrit aquí que les gestionnaires d'événements sont connus pour être une cause de 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 aquí .

Et enfin, ne tombez pas dans le piège de penser que Javascript supprimer est la réponse. Il semble que beaucoup le suggèrent, mais il ne fera pas l'affaire. Ici est une excellente référence pour comprendre supprimer par Kangax.

1 votes

Peut-être pouvez-vous montrer quelques jsFiddle pour le prouver. Merci

1 votes

Je confirme ce comportement. Mon cadre de travail utilise un arbre de mappage d'objet Javascript sur la disposition du dom. Chaque objet js fait référence à son élément dom. Même si j'appelle element.parentNode.removeChild pour supprimer des éléments, ils restent en vie et peuvent toujours être référencés. Ils ne sont simplement pas visibles dans l'arborescence normale du domaine.

0 votes

Oui, et ensuite, la suppression du pointeur global de cet objet de mappage js déverrouille comme par magie le ramasseur d'ordures. C'est un ajout important à la réponse acceptée.

14voto

Alireza Points 40192

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 le support des navigateurs est faible selon le W3C :

La méthode node.remove() est implémentée dans la spécification DOM 4. Mais en raison du faible support des navigateurs, vous ne devriez pas l'utiliser.

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

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

De même, dans les nouveaux cadres, vous pouvez utiliser des conditions pour supprimer un élément, par exemple *ngIf en Angular et en React, rendant des vues différentes, selon les conditions...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X