我有以下DOM结构:
var parent = document.querySelector(".test");
var navChild = parent.querySelectorAll("ul > li > a");
for (i = 0; i < navChild.length; i++) {
navChild[i].style.backgroundColor = "red";
}
console.log(navChild.lenght);
console.log(navChild);
<!-- begin snippet: js hide: false console: true babel: false -->
<ul>
<li class="test">
<a>ssss</a> <!--this will also be affected -->
<ul>
<li><a>fsfsf</a></li>
<li><a>sff</a></li>
<li><a>ggg</a></li>
</ul>
</li>
</ul>
我想使用vanilla javascript选择3个a
标记,并从li
开始使用类test。我将它放在parent
变量中,然后使用querySelectorAll尝试仅获取下一个列表中的a
标记。但是,返回的节点列表还包括第一个a
标记,即使它不是后代。这是我的代码:
var navChild = parent.querySelectorAll("ul > li > a");
真正奇怪的是,如果我只查询li
后代,我只得到3.所以我不明白为什么当我查询那个li
的子后代时我也得到了第一个a
标记是DOM上的两个级别。
我知道我可以使用jQuery做到这一点,但我不想使用它。
已编辑以显示我如何设置父变量
我在第一个a
标签上点击输入键盘按钮后,我试图将childs
标签添加到a
变量中我不想包含在子节点列表中。
var alinks = document.querySelectorAll('.test > a');
[].forEach.call(alinks, function(link){
link.addEventListener('keyup', function(e){
e.preventDefault();
if(e.keyCode === 13) {
var linkParent = e.target.parentElement;
var childs = menuParent.querySelectorAll('ul > li > a');
}
})
});
当我记录linkParent
时,它正确地被设置为li
类test
。我不明白为什么然后如果我从那里运行查询它仍然包含第一个a
标记。正如我之前所说,如果我只查询ul > li
,它会为我提供正确的li
代码。
答案 0 :(得分:3)
这是因为您尝试忽略的第一个<a>
标记仍然属于选择器规则ul > li > a
。因此,即使您以<li class="test">
作为根开始查询(顺便说一下,我也不知道为什么其他答案说文档仍然是根),第一个孩子它找到的元素是<a>
标记,实际上,它是<li>
的子节点,它是<ul>
的子节点。事实上,这种情况已经过去了......#34;您的指定根目录将被忽略。
修改强> 如果您希望将选择器规则限定为根,则可以使用此选项:
parent.querySelectorAll(":scope ul > li > a");
进一步澄清,browser CSS engines evaluate CSS rules right-to-left。在您看来,您希望浏览器从根(父<li class="test">
)开始,然后找到<ul>
标记,然后找到<li>
标记,然后找到{{1} } 标签。
但是,浏览器以root身份启动,但随后查找根目录下的所有<a>
标记。然后,它会检查<a>
标记是否在<a>
范围内,然后检查<li>
是否在<li>
范围内。所以<ul>
标签确实是根,但它不遵循选择器规则的从左到右的层次结构,之后是从右到左。
答案 1 :(得分:1)
这是因为您的第一个<a>
也匹配ul > li > a
,并且由于所述a
仍然是qSA被调用的元素的后代,因此它包含在NodeList中。
https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll#Javascript
Element.querySelector和Element.querySelectorAll在这方面有点古怪:虽然唯一匹配的元素必须是您调用它的元素的子元素,但选择器字符串仍然从文档级别开始 - 它不会通过首先隔离元素及其后代来验证选择器。
const child = document.querySelector('#child');
const span = child.querySelector('#parent span');
console.log(span.textContent);
<div id="parent">
<div id="child">
<span>text</span>
</div>
</div>
答案 2 :(得分:0)
使用此选项定义var navChild = document.querySelectorAll("test > ul > li > a");
。我不得不使用一个运行的例子来解决这个问题。这将获得您想要的3个香草<a>
querySelectorAll()方法返回文档中与指定的CSS选择器匹配的所有元素,作为静态NodeList对象。
即使您在文档中设置父级,我也认为这是真的。
var navChild = document.querySelectorAll(".test > ul > li > a");
for (i = 0; i < navChild.length; i++) {
navChild[i].style.backgroundColor = "red";
}
//console.log(navChild.lenght);
//console.log(navChild);
<ul>
<li class="test">
<a>qqqq</a>
<ul>
<li><a>aaa</a></li>
<li><a>bbb</a></li>
<li><a>ccc</a></li>
</ul>
</li>
</ul>