web-dev-qa-db-fra.com

Quand NodeList est-il actif et quand est-il statique?

Depuis MDN pour NodeList :

Dans certains cas, la NodeList est une collection active, ce qui signifie que les changements dans le DOM sont reflétés dans la collection. Par exemple, Node.childNodes est en ligne:

 var parent = document.getElementById('parent');
 var child_nodes = parent.childNodes;
 console.log(child_nodes.length); // let's assume "2"
 parent.appendChild(document.createElement('div'));
 console.log(child_nodes.length); // should output "3"

Dans d'autres cas, la NodeList est une collection statique, ce qui signifie que toute modification ultérieure du DOM n'affecte pas le contenu de la collection. document.querySelectorAll renvoie une NodeList statique.

Alors .... un peu ennuyeux! Existe-t-il une référence centrale pour quelles méthodes retournent des listes actives et lesquelles retournent des listes statiques, sans avoir à vérifier individuellement toutes les différentes parties de l'API DOM? Y a-t-il une règle à l'œuvre ici?

55
temporary_user_name

Les informations sur chaque méthode détaillent si elle est en direct ou non, mais il ne semble pas y avoir de convention standard pour la déterminer.

document.getElementsByClassName() est un HTMLCollection et est actif.

document.getElementsByTagName() est un HTMLCollection et est actif.

document.getElementsByName() est un NodeList et est en direct.

document.querySelectorAll() est un NodeList et n'est pas en direct.

HTMLCollections semblent toujours être en direct

Une HTMLCollection est une liste de nœuds. Un nœud individuel peut être consulté soit par un index ordinal, soit par le nom ou les attributs id du nœud.

Remarque: Les collections dans le DOM HTML sont supposées être en direct, ce qui signifie qu'elles sont automatiquement mises à jour lorsque le document sous-jacent est modifié.

http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-75708506

Ainsi, les collections HTML sont toujours "dans le dom", alors qu'un nodeList est une construction plus générique qui peut ou non être dans le DOM.

Un objet NodeList est une collection de nœuds ... L'interface NodeList fournit l'abstraction d'une collection ordonnée de nœuds, sans définir ni contraindre la façon dont cette collection est implémentée. Les objets NodeList dans le DOM sont actifs.

http://www.w3.org/TR/DOM-Level-3-Core/core.html#td-live

Sonne bien, non?

Une collection est un objet qui représente une liste de nœuds DOM. Une collection peut être en direct ou statique. Sauf indication contraire, une collection doit être en direct.

http://www.w3.org/TR/2012/WD-dom-20120405/#collections

Les collections statiques seront donc indiquées comme telles dans la spécification. Donc, par cette logique, document.querySelectorAll() est une collection, mais c'est pas dans le DOM. Parce que si les collections peuvent être actives ou non, les collections in le DOM doit être actif ... Cette distinction n'est pas super utile.

Eh bien, voici une méthode rapide pour déterminer si un collection est actif; il ajoute un clone d'un membre de la collection au DOM (donc il correspondra au sélecteur), et vérifie si la longueur a changé, puis le supprime (donc la page n'est pas affectée)

[~ # ~] démo [~ # ~]

function isLive(collection) {
  if (collection.length < 1) {
    return undefined; //inconclusivw 
  }
  let body = document.getElementsByTagName('body')[0];
  let l1 = collection.length;
  let clone = collection.item(0).cloneNode();
  clone.style.display = "none";
  body.appendChild(clone);
  let l2 = collection.length;
  body.removeChild(clone);
  return l2 !== l1;
}



divs1 = document.getElementsByClassName('c');
console.log("document.getElementsByClassName('c'):",divs1.toString()); //"[object HTMLCollection]"


divs2 = document.querySelectorAll('.c');
console.log("document.querySelectorAll('.c'):     ",divs2.toString()); //"[object NodeList]"

divs3 = document.getElementsByName('mydiv');
console.log("document.getElementsByName('mydiv'): ",divs3.toString()); //"[object NodeList"]

console.log("isLive(divs1)",isLive(divs1)); //true
console.log("isLive(divs2)",isLive(divs2)); //false
console.log("isLive(divs3)",isLive(divs3)); //true
<html>

<body>
  <div class="c" name="mydiv">C1</div>
  <div class="c" name="mydiv">C2</div>
</body>

</html>
101
chiliNUT

Je ne sais pas s'il y a une référence centrale, mais cela article de blog dit:

document.getElementsByTagName(), document.getElementsByTagNameNS et document.getElementsByClassName() sont les seules options disponibles qui renvoient des listes de nœuds "en direct". En regardant ces méthodes, vous pouvez être découragé, mais ne le soyez pas.

3
Barmar