web-dev-qa-db-fra.com

Sélecteur d'enfant utilisant `querySelectorAll` sur une collection DOM

Supposons que vous ayez une liste avec des listes enfants imbriquées.

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

Et utilisez document.querySelectorAll() pour faire votre choix:

var ul = document.querySelectorAll("ul");

Comment utiliser la collection ul pour obtenir les éléments enfants directs?

ul.querySelectorAll("> li"); 
// Gives 'Error: An invalid or illegal string was specified'

Supposons que ul soit mis en cache d'une manière ou d'une autre (sinon j'aurais pu faire ul > li directement).

Dans jQuery cela fonctionne:

$("ul").find("> li");

Mais ce n'est pas le cas en querySelectorAll en natif. Des solutions?

23
Husky

La manière correcte d'écrire un sélecteur qui est "enraciné" dans l'élément en cours consiste à utiliser :scope .

ul.querySelectorAll(":scope > li");

Voir ma réponse ici pour une explication et une solution robuste, multi-navigateurs: https://stackoverflow.com/a/21126966/1170723

39
lazd

Étant donné que la ul renvoyée est une liste de noeuds, elle ne boucle pas implicitement sur son contenu, comme une collection jQuery. Vous devez utiliser ul[0].querySelectorAll() ou, mieux encore, sélectionner ul avec querySelector().

De plus, querySelectorAll() ne prendra pas > et travaillera à partir de son contexte actuel. Cependant, vous pouvez le faire fonctionner en utilisant lazd's answer (bien que vérifiez la compatibilité du navigateur), ou n'importe laquelle de ces solutions de contournement (qui ne devrait pas poser de problèmes de navigateur) ...

[].filter.call(ul.querySelectorAll("li"), function(element){
     return element.parentNode == ul;
}); 

jsFiddle .

Cela sélectionnera tous les éléments li qui sont des descendants de votre ul, puis supprimera ceux qui ne sont pas des descendants directs.

Sinon, vous pouvez obtenir tous les childNodes et ensuite les filtrer ...

[].filter.call(ul.childNodes, function(node) {
    return node.nodeType == 1 && node.tagName.toLowerCase() == 'li';
});

jsFiddle .

13
alex

Vous devez parcourir la NodeList renvoyée par document.querySelectorAll(), puis appeler element.querySelectorAll() pour chaque élément de cette liste.

0
Alnitak