javascript - 多个后代选择器,错误或误解?
问题描述
以下两种选择节点的方法不应该产生相同的结果吗?
let tmp = fruits.querySelector("ul:first-of-type li:first-of-type");
tmp = tmp.querySelector("span")
对比
let tmp = fruits.querySelector("ul:first-of-type li:first-of-type span");
(在此处查看实际操作)
我已经在 Firefox 和 chrome 中对此进行了测试。两种情况的结果不同。有人可以解释为什么吗?
堆栈片段中的示例:
let fruits = document.querySelector("[data-segment='fruits']");
console.log(fruits);
let tmp = fruits.querySelector("ul:first-of-type li:first-of-type")
tmp = tmp.querySelector("span")
console.log("Works:")
console.log(tmp)
console.log("Does not work:")
console.log(fruits.querySelector("ul:first-of-type li:first-of-type span"))
<main id="app" data-v-app="">
<section>
<h2>Tree</h2>
<ul role="tree">
<li role="treeitem" data-segment="fruits" aria-level="1" aria-setsize="3" aria-posinset="1" aria-expanded="true"><span tabindex="0">Fruits</span>
<ul role="group">
<li role="none" data-segment="oranges" aria-level="2" aria-setsize="5" aria-posinset="1"><span tabindex="-1">Oranges</span>
<!--v-if-->
</li>
<li role="none" data-segment="pineapple" aria-level="2" aria-setsize="5" aria-posinset="2"><span tabindex="-1">Pineapple</span>
<!--v-if-->
</li>
<li role="treeitem" data-segment="apples" aria-level="2" aria-setsize="5" aria-posinset="3" aria-expanded="false"><span tabindex="-1">Apples</span>
<ul role="group">
<li role="none" data-segment="macintosh" aria-level="3" aria-setsize="3" aria-posinset="1"><span tabindex="-1">Macintosh</span>
<!--v-if-->
</li>
<li role="none" data-segment="granny_smith" aria-level="3" aria-setsize="3" aria-posinset="2"><span tabindex="-1">Granny Smith</span>
<!--v-if-->
</li>
<li role="none" data-segment="fuji" aria-level="3" aria-setsize="3" aria-posinset="3"><span tabindex="-1">Fuji</span>
<!--v-if-->
</li>
</ul>
</li>
<li role="none" data-segment="bananas" aria-level="2" aria-setsize="5" aria-posinset="4"><span tabindex="-1">Bananas</span>
<!--v-if-->
</li>
<li role="none" data-segment="pears" aria-level="2" aria-setsize="5" aria-posinset="5"><span tabindex="-1">Pears</span>
<!--v-if-->
</li>
</ul>
</li>
<li role="none" data-segment="vegetables" aria-level="1" aria-setsize="3" aria-posinset="2"><span tabindex="-1">Vegetables</span>
<!--v-if-->
</li>
<li role="none" data-segment="grains" aria-level="1" aria-setsize="3" aria-posinset="3"><span tabindex="-1">Grains</span>
<!--v-if-->
</li>
</ul>
</section>
</main>
解决方案
文档对此进行了解释:
element = baseElement.querySelector(selectors);
返回值
baseElement
与指定组匹配的第一个后代元素selectors
。匹配时考虑元素的整个层次结构,包括元素集之外的元素,包括baseElement
及其后代;换句话说,selectors
首先应用于整个文档,而不是baseElement
,以生成潜在元素的初始列表。然后检查生成的元素以查看它们是否是baseElement
. 该querySelector
方法返回那些剩余元素的第一个匹配项。
(强调我的。)
让我们考虑一个简化的例子:
console.log(document.getElementById("a").querySelector("ul li span"));
<ul>
<li id="a"><span>A</span>
<ul>
<li><span>B</span></li>
</ul>
</li>
</ul>
这里,baseElement
是document.getElementById("a")
;selectors
是"ul li span"
。
document.querySelector("ul li span")
确实包括两个<span>
s,并且它们都在 inside baseElement
。<span>A</span>
恰好是这个集合中的第一个。
有一个相当新的伪类:scope
,在这里可能会有所帮助:
console.log(document.getElementById("a").querySelector(":scope ul li span"));
<ul>
<li id="a"><span>A</span>
<ul>
<li><span>B</span></li>
</ul>
</li>
</ul>
推荐阅读
- laravel - Laravel:检测控制器中的令牌不匹配
- google-cloud-platform - 在 Cloud SQL 中删除数据库的云函数
- javascript - 如何在 React 中修复 Framer Motion 动画?
- c++ - C++ 中的格式说明符
- db2 - 将 db2 数据库从一个实例复制到另一个实例
- html - 如何让推荐文本以纵向显示在移动设备上?
- c# - C# 统一。控制变量在值为 2 时导致循环
- azure - New-AzActionGroupReceiver 如何将语音呼叫设置为新的操作组?
- go - 不能在 GOPATH 模式下使用 path@version 语法
- python - Tkinter 按钮分散得很远,如何将它们放在一起?