我可以这样做:

<div id="myDiv">
   <div class="foo"></div>
</div>
myDiv = getElementById("myDiv");
myDiv.querySelectorAll("#myDiv > .foo");

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

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

我应该能够离开#myDiv关闭,但选择器是不合法的语法,因为它以>开始。

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


当前回答

下面的解决方案与到目前为止提出的解决方案不同,对我来说是可行的。

基本原理是首先选择所有匹配的子节点,然后过滤掉不是直接子节点的子节点。如果子元素没有具有相同选择器的匹配父元素,则子元素是直接子元素。

function queryDirectChildren(parent, selector) {
    const nodes = parent.querySelectorAll(selector);
    const filteredNodes = [].slice.call(nodes).filter(n => 
        n.parentNode.closest(selector) === parent.closest(selector)
    );
    return filteredNodes;
}

HTH!

其他回答

我只是没有尝试就这么做了。这样能行吗?

myDiv = getElementById("myDiv");
myDiv.querySelectorAll(this.id + " > .foo");

试一试,也许有用,也许没用。抱歉,但我现在不在电脑上尝试它(从我的iPhone回复)。

我会和你一起去的

var myFoo = document.querySelectorAll("#myDiv > .foo");
var myDiv = myFoo.parentNode;

我创建了一个函数来处理这种情况,我想我会分享它。

getDirectDecendent(elem, selector, all){
    const tempID = randomString(10) //use your randomString function here.
    elem.dataset.tempid = tempID;

    let returnObj;
    if(all)
        returnObj = elem.parentElement.querySelectorAll(`[data-tempid="${tempID}"] > ${selector}`);
    else
        returnObj = elem.parentElement.querySelector(`[data-tempid="${tempID}"] > ${selector}`);

    elem.dataset.tempid = '';
    return returnObj;
}

本质上,你所做的是生成一个随机字符串(randomString函数在这里是一个导入的npm模块,但你可以自己做),然后使用这个随机字符串来确保你在选择器中得到你期望的元素。然后你就可以自由使用>了。

我没有使用id属性的原因是id属性可能已经被使用了,我不想重写它。

好问题。在被问到这个问题的时候,普遍实现的“组合根查询”(John Resig这样称呼它们)的方法还不存在。

现在引入了:scope伪类。它不支持[pre- chromium]版本的Edge或IE,但Safari已经支持了几年。使用它,你的代码可以变成:

let myDiv = getElementById("myDiv");
myDiv.querySelectorAll(":scope > .foo");

请注意,在某些情况下,您也可以跳过. queryselectorall,并使用其他老式的DOM API特性。例如,不是myDiv。querySelectorAll(":scope > *")你可以只写myDiv。比如孩子。

Otherwise if you can't yet rely on :scope, I can't think of another way to handle your situation without adding more custom filter logic (e.g. find myDiv.getElementsByClassName("foo") whose .parentNode === myDiv), and obviously not ideal if you're trying to support one code path that really just wants to take an arbitrary selector string as input and a list of matches as output! But if like me you ended up asking this question simply because you got stuck thinking "all you had was a hammer" don't forget there are a variety of other tools the DOM offers too.

下面的解决方案与到目前为止提出的解决方案不同,对我来说是可行的。

基本原理是首先选择所有匹配的子节点,然后过滤掉不是直接子节点的子节点。如果子元素没有具有相同选择器的匹配父元素,则子元素是直接子元素。

function queryDirectChildren(parent, selector) {
    const nodes = parent.querySelectorAll(selector);
    const filteredNodes = [].slice.call(nodes).filter(n => 
        n.parentNode.closest(selector) === parent.closest(selector)
    );
    return filteredNodes;
}

HTH!