Zip*_*ppy 4 html javascript css-selectors queryselector
给出以下标记(为了简洁起见,我仅包含相关部分)
<ul>
<li id="item">
<a href="#foo">Stuff</a>
<ul>
<li> <a href="#foo">Foo stuff</a></li>
<li><a href="#bar">Bar Stuff</a></li>
<li><a href="#foobar">Foo-Bar Stuff</a></li>
</ul>
</li>
</ul>
Run Code Online (Sandbox Code Playgroud)
假设我有一个对ID 为“item”的li元素的引用,我可以这样得到:
let item = document.querySelector('#item');
Run Code Online (Sandbox Code Playgroud)
现在我需要检索嵌套ul列表中的最后一个锚元素。为此,我将使用“最后一个子”选择器。这是我最初尝试的:
let lastLink = item.querySelector('li:last-child > a');
Run Code Online (Sandbox Code Playgroud)
我认为这可以解决问题,但可惜它实际上返回了标记中的第一个链接(“Stuff”)。我不太明白这一点,因为我的基本元素已经是“item”元素,我要求它在该基本元素中找到 li元素,这是其父元素的最后一个子元素,然后返回a元素从里面。
事实上,如果我这样做:
let lastLink = item.querySelector('li:last-child');
Run Code Online (Sandbox Code Playgroud)
它实际上返回嵌套 ul 列表中的最后一个 li 元素,那么为什么第一个选项不能简单地获取其中的'a'元素呢?
以下是我尝试过的其他一些有效的方法:
let lastLink = item.querySelector('#item li:last-child > a');
Run Code Online (Sandbox Code Playgroud)
但是,由于我已经有了对基本元素的引用,因此在此处指定其 ID 似乎毫无意义。这些也可以工作并返回正确的a元素:
let lastLink = item.querySelector('li ul li:last-child > a');
let lastLink = item.querySelector('li:last-child li:last-child > a');
Run Code Online (Sandbox Code Playgroud)
我的问题是,为什么第一个选项不起作用?如果有人能阐明原因,我将不胜感激
本质上做的rootElm.querySelector(selector)是:
for (const node of recursiveDescendantNodes) {
if (node.matches(selector)) {
return node;
}
}
Run Code Online (Sandbox Code Playgroud)
不会对其selector进行分解和分析以查看选择器的第一部分是否从根节点开始 - 通常,指定根节点所做的只是指示要搜索哪些后代。
由于第一个<a>指向#foo匹配传递的选择器,因此它被返回。
for (const node of recursiveDescendantNodes) {
if (node.matches(selector)) {
return node;
}
}
Run Code Online (Sandbox Code Playgroud)
console.log(
document.querySelector('#item > a').matches('li:last-child > a')
);Run Code Online (Sandbox Code Playgroud)
不过,有一种方法可以绕过这种行为,即使用:scope- 在受支持的浏览器中,表示“元素querySelector(或querySelectorAll)被调用”,这是您希望看到的功能。
<ul>
<li id="item">
<a href="#foo">Stuff</a>
<ul>
<li> <a href="#foo">Foo stuff</a></li>
<li><a href="#bar">Bar Stuff</a></li>
<li><a href="#foobar">Foo-Bar Stuff</a></li>
</ul>
</li>
</ul>Run Code Online (Sandbox Code Playgroud)
let item = document.querySelector('#item');
let lastLink = item.querySelector(':scope li:last-child > a');
console.log(lastLink);Run Code Online (Sandbox Code Playgroud)