Je me demandais, JavaScript offre une variété de méthodes pour obtenir le premier élément enfant à partir de n'importe quel élément, mais quelle est la meilleure? Par meilleur, je veux dire: la plupart des navigateurs compatibles, 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 le cas pour les formulaires, ou <div>
itération. Si je pouvais rencontrer des éléments de texte:
var child = elem.childNodes; // treat as NodeList
var child = elem.firstChild;
Autant que je sache, firstChild
utilise la liste de noeuds de childNodes
et firstElementChild
utilise children
. Je base cette hypothèse sur la référence MDN:
childNode
est une référence au premier élément enfant du nœud de l’élément, ounull
s’il n’en existe pas.
J'imagine qu'en termes de rapidité, la différence, s'il y en a une, sera presque nulle, puisque firstElementChild
est en réalité une référence à children[0]
et que l'objet children
est déjà en mémoire quand même.
Ce qui me jette, c'est l'objet childNodes
. Je l’ai utilisé pour examiner un formulaire, dans un élément de tableau. Alors que children
répertorie tous les éléments de formulaire, childNodes
semble également inclure des espaces à partir du code HTML:
console.log(elem.childNodes[0]);
console.log(elem.firstChild);
Tous les deux journal <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 reste collé au DOM, mais l’élément childNodes
semble fonctionner aux deux niveaux.
Pour revenir à ma question initiale, je suppose que si je veux l’objet le plus complet, childNodes
est la voie à suivre, mais en raison de son exhaustivité, il n’est peut-être pas le plus prévisible en termes de retour l'élément que je veux/attends à un moment donné. La prise en charge inter-navigateurs peut également s'avérer être un défi dans ce cas, bien que je puisse me tromper.
Quelqu'un pourrait-il clarifier la distinction entre les objets à portée de main? S'il existe une différence de vitesse, même négligeable, j'aimerais le savoir également. Si je vois tout cela de travers, n’hésitez pas à me renseigner.
PS: S'il vous plaît, s'il vous plaît, j'aime JavaScript, donc oui, je veux m'occuper de ce genre de chose. Des réponses telles que "jQuery traite cela pour vous" ne sont pas ce que je recherche, donc pas de balise jquery .
On dirait que tu y penses. Vous avez observé la différence entre childNodes
et children
, c'est-à-dire que childNodes
contient tous les nœuds, y compris les nœuds de texte composés entièrement d'espaces, tandis que children
est une collection de les nœuds enfants qui sont des éléments. C'est vraiment tout ce qu'il y a à faire.
Aucune de ces collections n’a rien d’imprévisible, bien qu’il y ait quelques problèmes à connaître:
childNodes
alors que les autres navigateurs l’incluentchildren
, tandis que les autres navigateurs ne comportent que des éléments.children
, firstElementChild
et les amis ne sont que des commodités, présentant une vue filtrée du DOM limitée à des éléments uniquement.
firstElementChild n'est peut-être pas disponible dans IE <9 (uniquement firstChild)
sur IE <9, firstChild est le premierElementChild car MS DOM (IE <9) ne stocke pas de nœuds de texte vides. Mais si vous le faites sur d'autres navigateurs, ils renverront des nœuds de texte vides ...
ma solution
child=(elem.firstElementChild||elem.firstChild)
cela donnera le premier enfant même sur IE <9
La méthode à utiliser entre navigateurs consiste à utiliser childNodes
pour obtenir NodeList
, puis créez un tableau de tous les nœuds 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;
}
_
Ceci est particulièrement facile si vous utilisez une bibliothèque d’utilitaires telle que 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 de la rédaction de cet article _:scope
_ est pris en charge sous Chrome, Firefox et Safari.
Pour ajouter aux autres réponses, il existe encore des différences notables ici, en particulier lorsque vous utilisez des éléments <svg>
.
J'ai utilisé à la fois .childNodes
et .children
et j'ai préféré travailler avec le HTMLCollection
fourni par le .children
getter.
Aujourd'hui, cependant, j'ai rencontré des problèmes avec IE/Edge qui échouaient lors de l'utilisation de .children
sur un <svg>
. Bien que .children
soit pris en charge dans IE sur des éléments HTML de base, il n'est pas pris en charge sur les documents/fragments de document, ou éléments SVG .
Pour moi, j'ai simplement pu récupérer les éléments nécessaires via .childNodes[n]
parce que je n'ai pas à me soucier de nœuds de texte superflus. Vous pourrez peut-être faire la même chose, mais comme mentionné plus haut, n'oubliez pas que vous risquez de rencontrer des éléments inattendus.
J'espère que cela aidera ceux qui se grattent la tête à essayer de comprendre pourquoi .children
fonctionne ailleurs dans leur js sur les IE modernes _ et échoue sur les éléments de document ou SVG.
Hé les gars, ne laissez pas l'espace blanc vous tromper. il suffit de tester cela dans un navigateur de console. utilisez javascript natif. Voici un exemple avec deux ensembles 'ul' avec la même classe. Vous n'avez pas besoin d'avoir votre liste "ul" sur une seule ligne pour éviter les espaces, utilisez simplement le nombre de tableaux pour sauter par-dessus les espaces.
Comment se déplacer dans les espaces vides 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>