【问题标题】:The subscription model behind CSS selectors?CSS 选择器背后的订阅模式?
【发布时间】:2012-09-25 08:31:57
【问题描述】:

使用 CSS 选择器,选择器字符串 body > h1.span 订阅树中特定类型的节点。有谁知道这是怎么做到的?

转换的选择器,浏览器如何选择结果集?有没有让它高效的诀窍?

我想对于节点订阅的整个结构以及在执行选择器查询时使用的结构存在某种分层类型树——但这只是一个猜测。

有人知道真正的答案吗?或者更有趣的是,基于 jQuery/CSS 搜索查询在树上进行动态查找的最佳方法是什么?

【问题讨论】:

  • 你所说的“转换”是什么意思?
  • @BoltClock 我只是想说做'$('body > h1').hide()'之类的东西
  • 你问的是 jQuery 选择器还是 CSS 选择器?这是两个不同的东西,因此实现方式也不同。
  • 动态选择器是指即使 DOM 发生变化也会匹配元素的选择器? (我想这就是您所说的订阅的意思。)
  • 是的,没错。我已经用一些细节扩展了我的答案。现在找一些参考资料...

标签: jquery css data-structures jquery-selectors css-selectors


【解决方案1】:

根据DOM,大多数主要浏览器都会处理页面并根据页面中的元素创建文档层次结构或文档树。在应用 CSS 时,他们通常会迭代文档树,以每个元素为基础,并在样式表中每个元素的候选选择器上执行right-to-left matching,然后根据CSSOM 应用基于这些匹配的 CSS 规则。这意味着对于像body > h1.span 这样的选择器,浏览器首先检查每个元素以查看它是否是具有span 类的h1,然后检查它是否是body 的直接后代。

根据实现的不同,可能会有一些优化来过滤更可能不匹配的情况。例如,在尝试任何其他匹配例程之前检查名称空间、标记名称、ID 或类名称,因为这些是区分元素的最常用方法。

这种逐元素匹配模式允许浏览器有效地“订阅”选择器对 DOM 中的更改,因为浏览器需要做的(我想)就是查看 DOM 中的更改并应用规则和重排相应更改的元素。

不过,这过于简单化了。它也主要指样式表中的选择器匹配。它没有描述每个选择器的实现,因为规范没有定义实现。

例如,浏览器以不同的方式实现 Selectors APIdocument.querySelector() 等),即使它使用 CSS selectors 来查询 DOM。特别是,没有任何订阅模式; Selectors API 方法返回的节点列表不会动态更新。来自§6.2 Finding Elements

querySelectorAll() 方法返回的 NodeList 对象必须是静态的,而不是 live([DOM-LEVEL-3-CORE],第 1.1.1 节)。对基础文档结构的后续更改不得反映在NodeList 对象中。这意味着该对象将包含一个匹配的 Element 节点列表,这些节点在创建列表时位于文档中。

根据this site上的一些答案,jQuery似乎也执行从右到左的选择器匹配,但我还没有找到任何支持来源。它还进行了许多优化,例如body 和优先读取 ID 选择器等。与 Selectors API 一样,jQuery 返回在调用其选择器引擎时匹配的静态节点列表;它不会订阅 DOM 中的更改并相应地更新节点列表(如果您需要订阅 DOM 更改并委托事件处理程序,则需要使用 .on() 或带有选择器的类似方法)。

值得注意的是,jQuery 采用的一项主要优化是遵循 Selectors API 以首先匹配选择器。这意味着它使用浏览器的 native 实现而不是 JavaScript。如果选择器是有效的 CSS 并且受支持,document.querySelectorAll() 返回一个节点列表。如果出错,jQuery 会退回到它自己的选择器引擎 Sizzle 来查询 DOM。

同样,它与浏览器对 CSS 选择器的实现并不完全相同,特别是因为 jQuery 选择器和 CSS 选择器不是一回事,尽管其中一个是对另一个的改编。

【讨论】:

  • Sizzle 引擎是有趣的部分 ;-)
【解决方案2】:

您可能知道 CSS 规则是从右到左评估的,因此在您的示例中,首先扫描整个 DOM 以查找类 .span,然后通过标签 h1 过滤。

【讨论】:

  • 不,这不是从右到左匹配的工作方式。请参阅this answer 获取反例(称为预过滤而不是 RTL 匹配)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-28
  • 2018-10-19
  • 2020-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-08
相关资源
最近更新 更多