据我了解,使用时element.querySelector(),查询应从特定元素开始。
但是,当我使用下面的代码运行时,它始终选择DIV特定元素中的第一个标签。
const rootDiv = document.getElementById('test');
console.log(rootDiv.querySelector('div').innerHTML);
console.log(rootDiv.querySelector('div > div').innerHTML);
console.log(rootDiv.querySelector('div > div > div').innerHTML);
console.log(rootDiv.querySelector('div > div > div > div').innerHTML);
console.log(rootDiv.querySelector('div > div > div > div > div').innerHTML);Run Code Online (Sandbox Code Playgroud)
<div>
<div>
<div id="test">
<div>
<div>
This is content
</div>
</div>
</div>
</div>
</div>Run Code Online (Sandbox Code Playgroud)
如您所见,前几个结果是相同的。这是一个错误吗?还是会从文档开始查询?
Cer*_*nce 26
什么querySelector做的是找到一个元素在文档中的某个地方的CSS选择器过去了,匹配然后将检查发现的元素是你叫元素的后代querySelector上。它不是从被调用的元素开始并向下搜索-而是始终从文档级别开始,查找与选择器匹配的元素,并检查该元素是否也是调用上下文元素的后代。这有点不直观。
所以:
someElement.querySelector(selectorStr)
Run Code Online (Sandbox Code Playgroud)
就好像
[...document.querySelectorAll(selectorStr)]
.find(elm => someElement.contains(elm));
Run Code Online (Sandbox Code Playgroud)
一个可能的解决方案是使用:scope来指示您希望选择从而rootDiv不是从开始document:
someElement.querySelector(selectorStr)
Run Code Online (Sandbox Code Playgroud)
[...document.querySelectorAll(selectorStr)]
.find(elm => someElement.contains(elm));
Run Code Online (Sandbox Code Playgroud)
:scope 除Edge之外,所有现代浏览器均支持该功能。
当前接受的答案以某种方式对发生的事情提供了有效的逻辑解释,但实际上是错误的。
Element.querySelector触发针对树算法的选择器匹配,该算法从根元素开始,并检查其后代是否与选择器匹配。
选择器本身是绝对的,它对文档没有任何了解,甚至不需要将Element追加到任何内容。除了:scope属性之外,它也不关心调用该方法的根querySelector。
如果我们想自己重写它,那就更像
const walker = document.createTreeWalker(element, {
NodeFilter.SHOW_ELEMENT,
{ acceptNode: (node) => return node.matches(selector) && NodeFilter.FILTER_ACCEPT }
});
return walker.nextNode();
Run Code Online (Sandbox Code Playgroud)
const walker = document.createTreeWalker(element, {
NodeFilter.SHOW_ELEMENT,
{ acceptNode: (node) => return node.matches(selector) && NodeFilter.FILTER_ACCEPT }
});
return walker.nextNode();
Run Code Online (Sandbox Code Playgroud)
const rootDiv = document.getElementById('test');
console.log(querySelector(rootDiv, 'div>div').innerHTML);
function querySelector(element, selector) {
const walker = document.createTreeWalker(element,
NodeFilter.SHOW_ELEMENT,
{
acceptNode: (node) => node.matches(selector) && NodeFilter.FILTER_ACCEPT
});
return walker.nextNode();
};Run Code Online (Sandbox Code Playgroud)
区别在于此实现不支持特殊:scope选择器。
您可能会认为从文档开始或从根元素开始都是相同的,但不仅会在性能方面有所不同,而且还可以在元素未附加到任何文档的情况下使用此方法。
<div>
<div>
<div id="test">
<div>
<div>
This is content
</div>
</div>
</div>
</div>
</div>Run Code Online (Sandbox Code Playgroud)
以同样的方式,如果我们只有Document.querySelector,则在Shadow-DOM中无法匹配元素。
| 归档时间: |
|
| 查看次数: |
1049 次 |
| 最近记录: |