2 votes

Supprimer tous les childNodes en 0(1) sur l'élément DOM

Lorsque l'on regarde les childNodes d'un parentNode, la structure de données semble être un objet de type tableau.

Au lieu d'itérer à travers chaque childNode et de le supprimer, est-il possible de simplement supprimer l'objet de type tableau ?

Je pense ici aux performances et j'aimerais éviter d'itérer dans les enfants et de les supprimer un par un.

Dans mon cas, je crée des éléments Li enfants sur un Ul parent :

  _createLi(address) {
    const parentUl = document.querySelector("ul#parent");
    const li = document.createElement("li");
    li.appendChild(document.createTextNode(address));
    parentUl.appendChild(li);
  }

Je peux les enlever comme ça :

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

Cela fonctionne mais il faut itérer à travers chaque nœud. Comment supprimer tous les nœuds enfants en supprimant le tableau d'objets qui les contient, et est-ce possible en O(1) ?

2voto

plalx Points 14938

Je doute vraiment que les enfants puissent être retirés en O(1), même avec node.innerHTML = '' car l'implémentation sous-jacente peut très bien être une opération O(N).

Ce que vous devriez envisager pour améliorer les performances est de minimiser le nombre de reflux du DOM.

  1. Vous pourriez essayer de remplacer l'élément par un clone.

    const list = document.querySelector('ul'); const listClone = list.cloneNode(false); list.parentNode.replaceChild(listClone, list);

    <ul> <li>First</li> <li>Last</li> </ul>

  2. Vous pourriez essayer de retirer la liste du DOM, d'effectuer les manipulations et de la rajouter.

    withElOutOfFlow(document.querySelector('ul'), el => { while(el.lastChild) el.removeChild(el.lastChild); });

    function withElOutOfFlow(el, callback) { const parent = el.parentNode;

    if (!parent) { callback(e); return; }

    const nextSibling = el.nextSibling; parent.removeChild(el); callback(el);

    if (nextSibling) parent.insertBefore(el, nextSibling); else parent.appendChild(el); }

    <ul> <li>First</li> <li>Last</li> <ul>

2voto

zer00ne Points 3056

Mise à jour

Plus rapide que .cloneNode() y .replaceChild()

Gamme API

5% plus rapide que TOUS les exemples
(y compris la réponse acceptée)

L'exemple suivant est tiré du Gamme API :

const rng = document.createRange();
rng.selectNodeContents(document.querySelector('ul'));
rng.deleteContents();

le site Gamme traite les fragments d'un document qui comprennent des nœuds et du texte. Bien qu'elle semble lent , c'est en fait rapide y 100% compatible avec tous les navigateurs .

Méthodes de portée

.createRange()
.selectNodeContents()
.deleteContents()


.replaceWith() y .createElement()

15% plus lent que tous les exemples
Cette combinaison est plus rapide que la plupart des exemples et moins verbeuse (à l'exception de la fonction Gamme démo étant le plus rapide).

 document.querySelector('ul').replaceWith(document.createElement('ul'));

C'est 2 interactions DOM : Trouver la liste et la remplacer par une liste vide. Voir la Démo 1. Si vous souhaitez prendre en charge IE11 (ATM 2,26% de part mondiale) alors ne l'utilisez pas.


Démo 1

Gamme API

const rng = document.createRange();
rng.selectNodeContents(document.querySelector('ul'));
rng.deleteContents();

ul {
  min-height: 30px;
  min-width: 30px;
  outline: 1px dashed red;
}

<ul>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
</ul>

Démo 2

.replaceWith() y .createElement()

document.querySelector('ul').replaceWith(document.createElement('ul'));

ul {
  min-height: 30px;
  min-width: 30px;
  outline: 1px dashed red;
}

<ul>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
</ul>

.insertAdjacentHTML() & .createDocumentFragment()

50 % plus lent que tous les exemples
La meilleure façon d'optimiser toute manipulation DOM est de ne pas en avoir. Gardez l'accès au DOM au minimum - cela prend beaucoup de temps. Chaque fois que le moteur JS recherche un élément, il traverse l'arborescence du DOM, chaque fois qu'une balise est ajoutée ou supprimée, les nœuds (élément, texte, etc.) qui se trouvent déjà dans le DOM doivent être recalculés pour le positionnement et les dimensions, de sorte que même si le nombre de nœuds concernés n'est que peu élevé, cela peut se transformer en un processus exceptionnellement long pour le navigateur. C'est ce que l'on appelle le reflux et un problème similaire impliquant des styles CSS est appelé un repeint.


La démo suivante supprime toutes les <li> dans un <ul> avec 4 opérations DOM :

  1. Références <ul> -- 1 recherche

  2. Parent de référence de <ul> ajouter un fichier vide <ul> -- 1 recherche, 1 ajout

  3. Créer un documentFragment et ajouter l'original <ul> à elle -- 1 retrait

.insertAdjacentHTML() Rendu non destructif htmlString en HTML et il est hautement optimisé .

.createDocumentFragment() ne touche jamais le DOM et ce qui y est attaché ne touche plus le DOM.


Démo 3

.insertAdjacentHTML y .createDocumentFragment()

// Reference the <ul>
const list = document.querySelector('ul');

// Reference parent of <ul> append an empty <ul>
list.parentElement.insertAdjacentHTML('beforeend', `<ul></ul>`);

// Create a document fragment and append original <ul> to it
document.createDocumentFragment().appendChild(list);

ul {
  min-height: 30px;
  min-width: 30px;
  outline: 1px dashed red;
}

<ul>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
  <li>ITEM</li>
</ul>

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