javascript - 使用 Element.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>
假设我引用了 ID 为“item”的li元素,我可以这样得到:
let item = document.querySelector('#item');
现在我需要检索嵌套ul列表中的最后一个锚元素。为此,我将使用“last-child”选择器。这是我最初尝试的:
let lastLink = item.querySelector('li:last-child > a');
我认为这可以解决问题,但可惜它实际上返回了标记中的第一个链接('Stuff')。我不太明白这一点,因为我的基本元素已经是“项目”元素,我要求它在该基本元素中找到li元素,该元素是其父元素的最后一个子元素,然后返回a元素从里面。
确实,如果我这样做:
let lastLink = item.querySelector('li:last-child');
它实际上返回嵌套 ul 列表中的最后一个 li 元素,那么为什么第一个选项不能简单地获取其中的“a”元素呢?
以下是我尝试过的其他一些有效的方法:
let lastLink = item.querySelector('#item li:last-child > a');
但是,由于我已经引用了基本元素,因此在此处指定其 ID 似乎毫无意义。这些也可以工作并返回正确的 a元素:
let lastLink = item.querySelector('li ul li:last-child > a');
let lastLink = item.querySelector('li:last-child li:last-child > a');
我的问题是,为什么第一个选项不起作用?感谢是否有人可以阐明原因
解决方案
做rootElm.querySelector(selector)
本质上是:
for (const node of recursiveDescendantNodes) {
if (node.matches(selector)) {
return node;
}
}
没有分解和分析选择器的selector
第一部分是否开始低于根节点 - 通常,指定根节点所做的只是指示要搜索的后代。
由于第一个<a>
指向#foo
的选择器与传递的选择器匹配,因此它被返回。
console.log(
document.querySelector('#item > a').matches('li:last-child > a')
);
<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>
不过,有一种方法可以绕过这种行为,:scope
在受支持的浏览器中使用 - 表示“元素querySelector
(或querySelectorAll
)被调用”,这是您希望看到的功能。
let item = document.querySelector('#item');
let lastLink = item.querySelector(':scope li:last-child > a');
console.log(lastLink);
<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>
推荐阅读
- arrays - How to set array to equal to values in 2D array, in column stored in a third array?
- scala - format field values for a list of case class
- php - 为什么它不显示几个月的所有日子?
- mysql - 对具有多个 INNER JOIN 的多个列进行 GROUP BY
- struts-1 - 动作表单bean继承
- java - 从包含多个
- javascript - 当我使用拖放时,拖动对象部署在 img 内部而不是 div
- coldfusion - 如何在 ColdFusion 中实现 recaptcha v3?
- python - 与 python 的连接问题:badstatusline
- python - UFC 数据集 InvalidArgumentError 断言失败:[Label IDs must < n_classes] [Condition x < y did not hold element-wise:]