【问题标题】:Unexpected results using Element.querySelector使用 Element.querySelector 的意外结果
【发布时间】:2021-12-13 05:46:08
【问题描述】:

鉴于以下标记(为简洁起见,我仅包含相关部分)

<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 元素,该元素是其最后一个子元素parent,然后从其中返回 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');  

我的问题是,为什么第一个选项不起作用?感谢是否有人可以解释原因

【问题讨论】:

  • 几乎听起来可能是浏览器错误。出于好奇,您是否曾在多个浏览器中尝试过?
  • 你期望 .querySelector() 像 jQuery .find() 一样工作。 querySelector() 在其 searchj 中包含起始元素。

标签: javascript html css-selectors queryselector


【解决方案1】:

执行rootElm.querySelector(selector) 本质上是:

for (const node of recursiveDescendantNodes) {
  if (node.matches(selector)) {
    return node;
  }
}

selector 没有被分解和分析以查看选择器的第一部分是否开始低于根节点 - 通常,指定根节点所做的只是指示要搜索的后代。

由于指向#foo 的第一个&lt;a&gt; 与传递的选择器匹配,所以它被返回。

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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-15
    相关资源
    最近更新 更多