使用querySelectorAll检索直接子项

mat*_*tsh 91 javascript dom css-selectors

我能够做到这一点:

<div id="myDiv">
   <div class="foo"></div>
</div>
Run Code Online (Sandbox Code Playgroud)
myDiv = getElementById("myDiv");
myDiv.querySelectorAll("#myDiv > .foo");
Run Code Online (Sandbox Code Playgroud)

也就是说,我可以成功检索myDiv具有类的元素的所有直接子元素.foo.

问题是,让我困扰的是我必须#myDiv在选择器中包含它,因为我在myDiv元素上运行查询(所以它显然是多余的).

我应该能够离开#myDiv,但是选择器不是合法的语法,因为它以a开头>.

有谁知道如何编写一个选择器,它只获取运行选择器的元素的直接子元素?

laz*_*azd 114

有谁知道如何编写一个选择器,它只获取运行选择器的元素的直接子元素?

编写一个"根"到当前元素的选择器的正确方法是使用:scope.

var myDiv = getElementById("myDiv");
var fooEls = myDiv.querySelectorAll(":scope > .foo");
Run Code Online (Sandbox Code Playgroud)

但是, 浏览器支持有限,如果您想使用它,则需要垫片.为此,我构建了scopedQuerySelectorShim.

  • FWIW 这似乎[现在除了 IE 之外的所有地方都得到完全支持](https://caniuse.com/?search=%3Ascope)。 (6认同)
  • @Adrian Moisa ::范围在任何地方都没有被弃用.您可能会将其与scoped属性混淆. (4认同)
  • 值得一提的是`:scope`规范目前是"工作草案",因此可能会有所变化.如果/当它被采用时,它可能仍会像这样工作,但是在我看来,这是"正确的方法". (3认同)
  • 看起来它在此期间已被弃用 (2认同)

nat*_*evw 53

好问题,但是正如你所看到的那样,John Resig没有办法为"组合根源查询" 命名.

但是,在某些情况下,您可以跳过.querySelectorAll并使用其他良好的老式DOM API功能.例如,myDiv.querySelectorAll(":scope > *")您可以只写myDiv.children,而不是不受支持.

遗憾的是,如果不添加更多自定义过滤器逻辑(例如查找:scope其中的myDiv.getElementsByClassName("foo")),我无法想出一种处理您的情况的方法,如果您尝试支持一个真正只想将任意选择器字符串作为一个代码路径的代码路径,那么这显然不太理想.输入和匹配列表作为输出!但是,如果像我一样,你最终会问这个问题只是因为你一直在思考"你所拥有的只是一把锤子",不要忘记DOM也提供了各种其他工具.

  • `myDiv.getElementsByClassName(“ foo”)`与`myDiv.querySelectorAll(“&gt; .foo”)`不同,它更类似于`myDiv.querySelectorAll(“。foo”)`(实际上是这样工作的) ),因为它找到所有后代`.foo`s而不是子代。 (2认同)
  • `:scope` 现在似乎已在除 Internet Explorer(已被 MS Edge 取代)之外的[所有主流浏览器](https://caniuse.com/mdn-css_selectors_scope) 中实现,因此可以毫无保留地使用它,除非您需要以支持IE。 (2认同)

the*_*axx 11

我用这个:

您可以避免键入“myDiv”两次并使用箭头。
当然,总是有更多的可能性。
可能需要现代浏览器。


<!-- Sample Code -->

<div id="myDiv">
    <div class="foo">foo 1</div>
    <div class="foo">foo 2
        <div class="bar">bar</div>
    </div>
    <div class="foo">foo 3</div>
</div>
Run Code Online (Sandbox Code Playgroud)
// Return HTMLCollection (Matches 3 Elements)

var allMyChildren = document.querySelector("#myDiv").children;
Run Code Online (Sandbox Code Playgroud)
// Return NodeList (Matches 7 Nodes)

var allMyChildren = document.querySelector("#myDiv").childNodes;
Run Code Online (Sandbox Code Playgroud)
// Match All Children With Class Of Foo (Matches 3 Elements)

var myFooChildren = document.querySelector("#myDiv").querySelectorAll(".foo");
Run Code Online (Sandbox Code Playgroud)
// Match Second Child With Class Of Foo (Matches 1 Element)

var mySecondChild = document.querySelector("#myDiv").querySelectorAll(".foo")[1];
Run Code Online (Sandbox Code Playgroud)
// Match All Children With Class Of Bar (Matches 1 Element)

var myBarChild = document.querySelector("#myDiv").querySelector(".bar");
Run Code Online (Sandbox Code Playgroud)
// Match All Elements In "myDiv" (Matches 4 Elements)

var myDescendants = document.querySelector("#myDiv").querySelectorAll("*");
Run Code Online (Sandbox Code Playgroud)


csu*_*cat 7

这是一个用 vanilla JS 编写的灵活方法,它允许您仅对元素的直接子元素运行 CSS 选择器查询:

var count = 0;
function queryChildren(element, selector) {
  var id = element.id,
      guid = element.id = id || 'query_children_' + count++,
      attr = '#' + guid + ' > ',
      selector = attr + (selector + '').replace(',', ',' + attr, 'g');
  var result = element.parentNode.querySelectorAll(selector);
  if (!id) element.removeAttribute('id');
  return result;
}
Run Code Online (Sandbox Code Playgroud)

  • JavaScript 不是并行执行的,因此可能性实际上为零。 (10认同)

Ran*_*all 5

如果您确定该元素是唯一的(例如您使用 ID 的情况):

myDiv.parentElement.querySelectorAll("#myDiv > .foo");
Run Code Online (Sandbox Code Playgroud)

对于更“全局”的解决方案:(使用matchesSelector shim

function getDirectChildren(elm, sel){
    var ret = [], i = 0, l = elm.childNodes.length;
    for (var i; i < l; ++i){
        if (elm.childNodes[i].matchesSelector(sel)){
            ret.push(elm.childNodes[i]);
        }
    }
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

哪里elm是你的父元素,sel是你的选择器。也可以完全用作原型。