Meilleure façon d'obtenir des nœuds enfants

je me demandais, JavaScript offre une variété de méthodes pour obtenir le premier élément enfant de n'importe quel élément, mais quel est le meilleur? Par meilleur, je veux dire: le plus compatible avec les navigateurs, le plus rapide, le plus complet et le plus prévisible en matière de comportement. Une liste de méthodes / propriétés que j'utilise comme alias:

var elem = document.getElementById('container');
var child = elem.children[0];
var child = elem.firstElementChild; // == children[0]

cela fonctionne pour les deux cas:

var child = elem.childNodes[0]; // or childNodes[1], see below

C'est dans le cas de formulaires, ou <div> itération. Si je peut éléments textuels de la rencontre:

var child = elem.childNodes; // treat as NodeList
var child = elem.firstChild;

pour autant que je sache, firstChild utilise le NodeList de childNodes , et firstElementChild utilise children . Je fonde cette hypothèse sur la référence MDN:

childNode est une référence au premier élément enfant du noeud d'élément, ou null s'il n'y en a pas.

je devine que, en termes de vitesse, la différence, si tout, sera presque rien, puisque firstElementChild est effectivement une référence à children[0] , et l'objet children est déjà en mémoire de toute façon.

ce qui me jette, c'est l'objet childNodes . Je l'ai utilisé pour regarder une forme, dans un élément de table. Alors que children liste tous les éléments de forme, childNodes semble également inclure des espaces à partir du code HTML:

console.log(elem.childNodes[0]);
console.log(elem.firstChild);

les deux log <TextNode textContent="n ">

console.log(elem.childNodes[1]);
console.log(elem.children[0]);
console.log(elem.firstElementChild);

Tous les journaux <input type="text" ... > . Comment venir? Je comprendrais qu'un objet me permettrait de travailler avec le code HTML "brut", tandis que l'autre colle au DOM, mais l'élément childNodes semble fonctionner sur les deux niveaux.

pour revenir à ma question initiale, ma conjecture serait: si je veux l'objet le plus complet, childNodes est la voie à suivre, mais en raison de son exhaustivité, il pourrait ne pas être le plus prévisible en termes de retour l'élément que je veux/attends à tout moment. La prise en charge par navigateur croisé pourrait également s'avérer un défi dans ce cas, bien que je puisse me tromper.

Quelqu'un pourrait-il clarifier la distinction entre les objets en question? S'il y a une différence de vitesse, même minime, j'aimerais le savoir aussi. Si je me trompe, n'hésitez pas à m'éduquer.


PS: s'il vous Plaît, s'il vous plaît, j'aime le JavaScript, donc oui, je veux faire face à cette genre de chose. Des réponses comme" jQuery s'occupe de ça pour vous "ne sont pas ce que je cherche, donc pas de jQuery tag.

199
demandé sur Xufox 2012-04-30 13:25:35

5 réponses

on dirait que tu réfléchis trop. Vous avez observé la différence entre childNodes et children , qui est que childNodes contient tous les noeuds, y compris les noeuds de texte consistant entièrement en espace blanc, tandis que children est une collection de seulement les noeuds enfants qui sont des éléments. C'est vraiment tout là est à lui.

il n'y a rien d'imprévisible au sujet de l'une ou l'autre collection, bien qu'il y ait quelques problèmes à être au courant:

  • IE <= 8"
  • IE <= 8 inclut les noeuds de commentaires dans children alors que les autres navigateurs ont seulement des éléments

children , firstElementChild et les amis sont juste des commodités, présentant une vue filtrée du DOM limité aux éléments justes.

187
répondu Tim Down 2013-09-12 08:25:41

firstElementChild peuvent ne pas être disponibles dans IE<9 (seulement firstChild)

sur IE<9 firstChild est le firstElementChild parce que MS DOM (IE<9) ne stocke pas de noeuds de texte vides. Mais si vous le faites sur d'autres navigateurs, ils retourneront des noeuds de texte vides...

ma solution

child=(elem.firstElementChild||elem.firstChild)

Cela donnera le premier enfant même sur IE<9

22
répondu neu-rah 2018-01-17 19:07:22

la façon de faire cross browser est d'utiliser childNodes pour obtenir NodeList , puis faire un tableau de tous les noeuds avec nodeType ELEMENT_NODE .

/**
 * Return direct children elements.
 *
 * @param {HTMLElement}
 * @return {Array}
 */
function elementChildren (element) {
    var childNodes = element.childNodes,
        children = [],
        i = childNodes.length;

    while (i--) {
        if (childNodes[i].nodeType == 1) {
            children.unshift(childNodes[i]);
        }
    }

    return children;
}

http://jsfiddle.net/s4kxnahu /

C'est particulièrement facile si vous utilisez une bibliothèque utilitaire comme lodash :

/**
 * Return direct children elements.
 *
 * @param {HTMLElement}
 * @return {Array}
 */
function elementChildren (element) {
    return _.where(element.childNodes, {nodeType: 1});
}

futur:

vous pouvez utiliser querySelectorAll en combinaison avec :scope pseudo-classe (correspond à l'élément qui est le point de référence du sélecteur):

parentElement.querySelectorAll(':scope > *');

au moment d'écrire ce :scope est supporté dans Chrome, Firefox et Safari.

15
répondu Gajus 2015-08-20 09:06:24

les gars, ne laissez pas l'espace blanc vous tromper. il suffit de le tester dans un navigateur de console. utilisez le javascript natif. Voici un exemple avec deux ensembles ul avec la même classe. Vous n'avez pas besoin d'avoir votre liste 'ul' tout en une ligne pour éviter l'espace blanc utilisez juste votre nombre de tableaux pour sauter au-dessus de l'espace blanc.

comment se déplacer espace blanc avec querySelector() puis childNodes[] js fiddle link: https://jsfiddle.net/aparadise/56njekdo /

var y = document.querySelector('.list');
var myNode = y.childNodes[11].style.backgroundColor='red';

<ul class="list">
    <li>8</li>
    <li>9</li>
    <li>100</li>
</ul>

<ul class="list">
    <li>ABC</li>
    <li>DEF</li>
    <li>XYZ</li>
</ul>
1
répondu andre paradise 2016-03-27 07:01:56

juste pour ajouter aux autres réponses, il y a encore des différences notables ici, particulièrement en ce qui concerne les éléments <svg> .

j'ai utilisé à la fois .childNodes et .children et j'ai préféré travailler avec le HTMLCollection livré par le .children getter.

Aujourd'hui, cependant, j'ai rencontré des problèmes avec IE/Edge failing en utilisant .children sur un <svg> . Tandis que .children est supporté dans IE sur HTML de base éléments, il n'est pas pris en charge sur le document/document de fragments, ou éléments SVG .

pour moi, j'ai pu simplement saisir les éléments nécessaires via .childNodes[n] parce que je n'ai pas de nœuds de texte étrangers à m'inquiéter. Vous pouvez peut-être faire la même chose, mais comme nous l'avons mentionné plus haut, n'oubliez pas que vous pourriez rencontrer des éléments inattendus.

j'Espère que cela est utile à quelqu'un se gratter la head essayant de comprendre pourquoi .children travaille ailleurs dans leur js sur IE moderne et échoue sur des éléments de document ou SVG.

0
répondu slothluvchunk 2016-06-21 17:44:57