web-dev-qa-db-fra.com

Supprimer tous les éléments enfants d'un nœud DOM en JavaScript

Comment puis-je supprimer tous les éléments enfants d'un nœud DOM en JavaScript?

Disons que j'ai le code HTML (laid) suivant:

<p id="foo">
    <span>hello</span>
    <div>world</div>
</p>

Et je prends le noeud que je veux comme ça:

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

Comment puis-je supprimer les enfants de foo afin qu'il ne reste que <p id="foo"></p>?

Puis-je faire juste:

myNode.childNodes = new Array();

ou devrais-je utiliser une combinaison de removeElement?

J'aimerais que la réponse soit tout droit sorti de DOM; points supplémentaires si vous fournissez également une réponse dans jQuery avec la réponse DOM uniquement.

656
Polaris878

Option 1 (beaucoup plus lente, voir les commentaires ci-dessous):

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

Option 2 (beaucoup plus rapide):

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

La réponse actuellement acceptée est fausse à propos du ralentissement de innerHTML (du moins dans IE et Chrome), comme indiqué correctement dans m93a.

Chrome et FF sont considérablement plus rapides avec cette méthode (qui détruira les données jquery attachées):

var cNode = node.cloneNode(false);
node.parentNode.replaceChild(cNode ,node);

dans une seconde lointaine pour FF et Chrome, et le plus rapide dans IE:

node.innerHTML = '';

InnerHTML ne détruira pas vos gestionnaires d'événements ni ne cassera les références jQuery, il est également recommandé comme solution ici: https://developer.mozilla.org/en-US/docs/Web/ API/Element.innerHTML

La méthode de manipulation DOM la plus rapide (toujours plus lente que les deux précédentes) est la suppression de la plage, mais les plages ne sont pas prises en charge avant IE9.

var range = document.createRange();
range.selectNodeContents(node);
range.deleteContents();

Les autres méthodes mentionnées semblent comparables, mais beaucoup plus lentes que innerHTML, à l'exception de la requête aberrante jquery (1.1.1 et 3.1.1), qui est considérablement plus lente que toute autre chose:

$(node).empty();

Preuve ici:

http://jsperf.com/innerhtml-vs-removechild/167http://jsperf.com/innerhtml-vs-removechild/300 https://jsperf.com/remove-all-child-elements-of-a-domode-node-in-javascript (Nouvelle URL pour le redémarrage de jsperf car l'édition de l'ancienne URL isn ' t de travail)

La "boucle par test" de Jsperf est souvent comprise comme une "per-itération", et seule la première itération a des nœuds à supprimer, ainsi les résultats n'ont pas de sens. Au moment de la publication, des tests dans ce fil avaient été configurés de manière incorrecte.

84
npjohns
var myNode = document.getElementById("foo");
var fc = myNode.firstChild;

while( fc ) {
    myNode.removeChild( fc );
    fc = myNode.firstChild;
}

S'il existe un risque que vos descendants soient affectés par jQuery, vous devez utiliser une méthode permettant de nettoyer les données jQuery.

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

La méthode jQuery .empty() garantira que toutes les données associées à jQuery avec les éléments à supprimer seront nettoyées.

Si vous utilisez simplement les méthodes DOM pour supprimer les enfants, ces données seront conservées.

40
user113716

Si vous utilisez jQuery:

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

Si vous ne le faites pas:

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

Utilisez le Javascript moderne, avec remove!

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

Il s'agit d'une méthode plus récente pour écrire la suppression de nœud dans ES5. Il est Vanilla JS et lit beaucoup plus agréable que les versions précédentes.

La plupart des utilisateurs devraient avoir des navigateurs modernes ou vous pouvez transpiler si nécessaire.

Support par navigateur - 91% Avr 2018

25
Gibolt

Le plus rapide...

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

Merci à Andrey Lushnikov pour son lien vers jsperf.com (site sympa!).

EDIT: pour que ce soit clair, il n'y a pas de différence de performances dans Chrome entre firstChild et lastChild. La première réponse montre une bonne solution pour la performance.

18
Gabe Halsmer

Si vous voulez seulement avoir le noeud sans ses enfants, vous pouvez aussi en faire une copie comme ceci:

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

Cela dépend de ce que vous essayez d’atteindre.

9
DanMan

Voici une autre approche:

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
element.textContent = '';

C'est comme innerText, sauf standard. C'est un peu plus lent que removeChild(), mais il est plus facile à utiliser et ne fera pas une grande différence de performances si vous n'avez pas trop de choses à supprimer.

5
bjb568

En réponse à DanMan, Maarten et Matt. Cloner un nœud, définir le texte est en effet un moyen viable dans mes résultats.

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

De plus, cela fonctionne pour les noeuds ne figurant pas dans le dom qui retournent la valeur null lorsqu'ils tentent d'accéder au parentNode. En outre, si vous devez être en sécurité, un nœud est vide avant d'ajouter du contenu, cela est très utile. Considérez le cas d'utilisation ci-dessous.

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

Je trouve cette méthode très utile pour remplacer une chaîne dans un élément. Si vous ne savez pas exactement ce que le nœud va contenir, au lieu de vous demander comment nettoyer le désordre, recommencez à zéro.

4
jeroen

Il y a plusieurs options pour y parvenir:

Le plus rapide ():

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

Alternatives (plus lent):

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

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

Benchmark avec les options proposées

3
magiccrafter

j'ai vu des gens faire:

while (el.firstNode) {
    el.removeChild(el.firstNode);
}

alors quelqu'un a dit en utilisant el.lastNode est plus rapide

cependant, je pense que c'est le plus rapide:

var children = el.childNodes;
for (var i=children.length - 1; i>-1; i--) {
    el.removeNode(children[i]);
}

qu'est-ce que tu penses?

ps: ce sujet a été une bouée de sauvetage pour moi. mon addon firefox a été rejeté parce que j'ai utilisé innerHTML. C'est une habitude depuis longtemps. alors je foudn cela. et j'ai effectivement remarqué une différence de vitesse. à la charge, le innerhtml a mis du temps à se mettre à jour, mais passe à addElement son instant!

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

Cela supprimera tous les nœuds de l'élément.

3
Henrik

Manière la plus simple de supprimer les nœuds enfants d'un nœud via Javascript

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

innerText est le gagnant! http://jsperf.com/innerhtml-vs-removechild/133 . Lors de tous les tests précédents, les domaines internes du nœud parent ont été supprimés à la première itération, puis innerHTML ou removeChild ont été appliqués à div vide.

2
Alexey

Utiliser une boucle de distance me semble le plus naturel:

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

Selon mes mesures dans Chrome et Firefox, il est environ 1,3x plus lent. Dans des circonstances normales, cela n'aura peut-être pas d'importance.

2
emu

Voici ce que je fais habituellement:

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

Et voila, plus tard, vous pouvez vider n'importe quel élément dom avec:

anyDom.empty()
1
Ado Ren

Généralement, JavaScript utilise des tableaux pour référencer des listes de nœuds DOM. Donc, cela fonctionnera bien si vous avez un intérêt à le faire via le tableau HTMLElements. A noter également, car j'utilise une référence à un tableau au lieu de JavaScript, cela devrait fonctionner dans n'importe quel navigateur, y compris IE.

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

Je viens de voir quelqu'un mentionner cette question dans une autre et j'ai pensé ajouter une méthode que je n'ai pas encore vue:

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

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

La fonction clear prend l'élément et utilise le nœud parent pour se remplacer par une copie sans ses enfants. Peu de gain de performance si l'élément est rare, mais lorsque l'élément a un ensemble de nœuds, les gains de performance sont réalisés.

0

Pourquoi ne suivons-nous pas la méthode la plus simple ici, "remove" en boucle à l'intérieur.

const foo = document.querySelector(".foo");
while (foo.firstChild) {
  foo.firstChild.remove();     
}
  • Sélection du parent div
  • Utilisation de la méthode "remove" dans une boucle While pour éliminer le premier élément enfant, jusqu'à ce qu'il n'en reste plus.
0
NEelansh VErma