Child selector using `querySelectorAll` on a DOM c

2019-02-02 04:32发布

Let's presume you got a list with nested child lists.

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

And use document.querySelectorAll() to make a selection:

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

How can i use the ul collection to get the direct child elements?

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

Let's presume ul is cached somehow (otherwise i could have done ul > li directly).

In jQuery this works:

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

But it doesn't in native querySelectorAll. Any solutions?

3条回答
淡お忘
2楼-- · 2019-02-02 05:11

The correct way to write a selector that is "rooted" to the current element is to use :scope.

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

See my answer here for an explanation and a robust, cross-browser solution: https://stackoverflow.com/a/21126966/1170723

查看更多
走好不送
3楼-- · 2019-02-02 05:25

Because the ul returned is a NodeList, it doesn't implicitly loop over its contents like a jQuery collection. You'd need to use ul[0].querySelectorAll() or better still select the ul with querySelector().

Besides that, querySelectorAll() won't take a > and work from its current context. However, you can get it to work using lazd's answer (though check the browser compatibility), or any of these workarounds (which should have no browser issues)...

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

jsFiddle.

This will select all li elements that are descendants of your ul, and then remove the ones which are not direct descendants.

Alternatively, you could get all childNodes and then filter them...

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

jsFiddle.

查看更多
Luminary・发光体
4楼-- · 2019-02-02 05:29

You need to iterate over the NodeList returned by document.querySelectorAll() and then call element.querySelectorAll() for each element in that list.

查看更多
登录 后发表回答