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, ounull
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.
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.
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
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.
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>
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.