以下两种选择节点的方法不应该产生相同的结果吗?
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");(在操作here中查看它)
我已经在火狐和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>
发布于 2021-04-11 19:03:25
documentation对此进行了解释:
元素=baseElement.querySelector(选择器);
返回值
与指定的selectors组匹配的baseElement的第一个后代元素。匹配时会考虑整个元素层次结构,包括元素集之外的元素,包括 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>,而且它们都在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>
发布于 2021-04-11 19:03:54
如果你不知道el.querySelector(selector)在后台是如何工作的,它可能会返回令人惊讶的结果。
el.querySelector(selector)实际情况是这样的:
(el, selector) => [...document.querySelectorAll(selector)].filter(node => el !== node && el.contains(node))[0]请参阅此示例:
const el = document.getElementById('outer');
const selector = 'span > span';
console.log(el.querySelector(selector).id); // logs "inner", not "innermost"
// same as if you did
console.log([...document.querySelectorAll(selector)].filter(node => el !== node && el.contains(node))[0].id);<span id="outermost">
<span id="outer">
<span id="inner">
<span id="innermost"></span>
</span>
</span>
</span>
因此,如果执行了document.querySelectorAll(selector),el.querySelector(selector)将返回中的第一个匹配项,该匹配项满足以下条件:找到的节点必须是el的后代。
更令人惊讶的是,如果您传递的selector没有匹配项,el.querySelector甚至会找到一个匹配项,因为selector的某些部分甚至不在el中
const el = document.getElementById('outer');
const selector = '#outermost > span > span';
console.log(el.querySelector(selector).id); // logs "inner"!
// same as if you did
console.log([...document.querySelectorAll(selector)].filter(node => el !== node && el.contains(node))[0].id);<span id="outermost">
<span id="outer">
<span id="inner">
<span id="innermost"></span>
</span>
</span>
</span>
https://stackoverflow.com/questions/67043990
复制相似问题