为何在#root上调用querySelector('.aa .bb')返回firstBB?是否为正确行为?
问题:querySelector调用结果不符合预期?
我存在困惑:为何代码中的变量$1的值为firstBB?我原本认为在#root元素上调用querySelector('.aa .bb')时,应该在#root的后代中查找class为aa的元素下的class为bb的元素(即secondBB)。使用Chrome版本:116.0.5845.188,请问这是querySelector的正确行为吗?
代码示例
JavaScript代码
const $1 = document.querySelector('#root').querySelector('.aa .bb'); const $2 = document.querySelector('#root').querySelector('.aa').querySelector('.bb'); document.querySelector('#result').innerHTML = `$1 is ${$1.id}; $2 is ${$2.id}`
HTML代码
<div class="aa" id="root"> <div class="bb" id="firstBB">xxx</div> <div class="aa"> <div class="bb" id="secondBB">xxx</div> </div> </div> <div>Result: <span id="result"></span></div>
解答
这确实是querySelector的正确行为,核心原因如下:
- 当在某个DOM元素上调用
querySelector(selector)时,选择器的匹配范围是该元素本身 + 它的所有后代元素,并非只局限于后代元素。 - 你的选择器
.aa .bb逻辑是:先找到带aa类的元素,再在它的后代里找带bb类的元素。而#root本身就带有aa类,所以它会被当作.aa的匹配目标,它的直接子元素#firstBB(带bb类)完全符合.aa .bb的匹配规则,因此被优先选中。
反观$2的写法:querySelector('.aa')会选中#root后代里第一个带aa类的元素(也就是嵌套的那个.aa),再调用querySelector('.bb')自然就找到它的子元素#secondBB,这和你最初的预期一致。
如果想让$1的选择器只匹配#root后代中的.aa .bb,可以用:scope关键字限定范围,:scope代表调用querySelector的元素本身,这样选择器就会只在该元素的后代里找.aa元素,再找它下面的.bb:
const $1 = document.querySelector('#root').querySelector(':scope .aa .bb');
内容的提问来源于stack exchange,提问作者White Wang
相关产品推荐
相关产品推荐

