【问题标题】:Is there a difference in performance between the child and descendant selectors?子选择器和后代选择器之间的性能是否存在差异?
【发布时间】:2016-01-10 06:41:47
【问题描述】:

我可以使用子组合符> 或仅表示任何后代的空格来编写 CSS 选择器。例如,我有这个 HTML 代码:

<span id='test'>
    <a href="#">Hello</a>
</span>

我可以通过以下两种方式编写我的 CSS 代码:

#test > a {
    ...
}

#test a {
    ...
}

就性能而言,编写以下 CSS 代码的最佳方式是什么?

【问题讨论】:

  • #test a 是后代选择器(即:孩子,或孩子的孩子等),#test &gt; a 是孩子选择器(即直系后代)......它们是'两者不一样,所以只需根据需要使用其中一个。
  • 没关系。使用一个有效的,并且最容易编写、理解和维护的。为什么你认为这可能很重要?
  • @torazaburo 你为什么认为这很重要?你是问我还是问 OP?无论如何,我只是想弄清楚两者并不相同并且有不同的建议,所以就像你说的那样使用有效的,并且最容易编写,理解和维护这也只是一个评论不是答案:)
  • 这是针对 OP 的,抱歉没有说清楚。
  • @torazaburo 首先,我认为尝试提高他们的技能,这永远不会受到伤害。但是,在这种情况下,这纯粹是出于好奇。我通常使用&gt; 选择器(在需要时),但我的一位同事向我指出,即使使用它也不会影响速度,就像示例中一样。

标签: css performance css-selectors micro-optimization


【解决方案1】:

Browsers parse selectors from right to left.

那么如果你使用#test &gt; a,对于页面中的每个a元素,浏览器都会检查其父元素是否有id="test"

但是,如果您使用#test a,对于页面中的每个a 元素,浏览器会检查它的某些祖先是否有id="test"。文档中不应该有很多这些元素,因此浏览器可能必须检查每个 a 的所有祖先。

我还没有进行任何测试,但我希望检查所有祖先比只检查父母要慢。

所以#test &gt; a 可能更快。

【讨论】:

  • 同意你的结论。更不用说选择器实际上做不同的事情,所以这种比较并不总是必要的。此外,大多数网页的性能差异可以忽略不计。您必须处理数千个元素才能注意到性能差异。在现实世界中,没有人抱怨选择器的性能。但这是会议和博客中的共同主题。
【解决方案2】:

请注意,两个选择器不会为您提供相同的输出!在您的示例中,确实如此。

但让我们检查下一个 HTML 代码,其中包含两个链接。

<div id="test">
    <p> lorum ipsum <a href="#">here</a> dolor </p>
    <a href="#">read more</a>
</div>

文本之间有一个链接,段落后面有一个链接,以允许用户阅读更多文本。 (例如在新闻网站上)。

如果你使用

#test a {
    ...
}

然后您将选择两个链接。

如果你使用

#test > a {
    ...
}

它只会选择#test的直接后代链接,即阅读更多链接!那是因为&gt;child combinator。段落中的链接不会被选中。

下面是一个sn-p,向您展示不同之处。

#test a {
  color: red;
}
#test > a {
  font-weight: bold;
  font-size: 18px;
}
<div id="test">
  <p>lorum ipsum <a href="#">here</a> dolor</p>
  <a href="#">read more</a>
</div>

如您所见,第二个 CSS 规则只编辑了第一个子 &lt;a&gt; 元素(“阅读更多”链接)。

现在,回到您关于您的情况下的性能的问题:如果您在下一个 HTML 部分同时使用这两个选择器

<div id="test">
    <a href="#">Hello</a>
</div>

性能方面,这里是一样的。

--edit1:对上面句子的澄清--

当使用选择器时,它从右到左检查。在这种的情况下,body中有一个div,div里面有一个link元素,性能是一样的。这是因为当使用#test &gt; a 时,它会检查所有链接以查看它的父级是否有id="test"。它不会进一步遍历树。

当使用#test a 时,它会检查链接元素的所有父元素(直到根),看看它是否有id="test"。由于在这种情况下在第一次父检查时已经找到了 div,因此它不必进一步遍历树。

但在其他情况下,当 div 不是文档中的唯一元素时,它当然会有所作为。您无法在此处比较差异,因为如前所述,结果不同。除非你确保给定的 div 下没有二级链接。那么&gt;的使用当然更快了。

-- 结束编辑--

但是,如果这个人扩展了上述 div 的内容,他/她可能会遇到意想不到的 CSS 样式。

但要了解整体性能,这实际上取决于您希望通过 CSS(样式化所有链接还是仅设置第一级?)和div#tree 中的 DOM 树(树的深度?)。

【讨论】:

  • 子组合器仅在第一级执行 BFS(=呼吸优先搜索)。如果没有那个 >,它会检查该 div 中的整个树。 所以我猜 OP 想知道的是,这是否会对性能产生任何有意义的差异,如果我确定只有一个孩子,我应该特别小心使用&lt;以避免巨大的性能损失?
  • 你确定它是 BFS 吗?选择器从右到左解析,而不是从左到右解析。所以#test &gt; a 只检查每个a 的父级。对于#test a,它是每个a 的所有祖先。
  • 首先,我不明白您为什么要在帖子的前半部分解释一些 OP 大概已经知道的事情。其次,当您说“性能方面,这里是一样的”时,我不明白您的意思。不,我认为不是。然后你继续说其他一些暗示它不一样的东西。是否相同?如果不一样,有多少不一样?
  • @torazaburo 你的评论是正确的。我已经添加了一个说明。尽管如此,它还是在比较苹果和梨,除非您确保该 div 中没有二级链接。那么情况也是一样的。
猜你喜欢
  • 1970-01-01
  • 2012-02-09
  • 2014-10-29
  • 2012-11-23
  • 2013-12-07
  • 1970-01-01
  • 2013-05-21
  • 2019-08-19
  • 1970-01-01
相关资源
最近更新 更多