使用CSS选择器获取元素 -- querySelector,querySelectorAll(HTML5)

标准

  • W3C Selector API Level 1为Document,DocumentFragment和Element追加了querySelector和querySelctorAll,原型为Element? querySelector(DOMString selectors)和 NodeList querySelectorAll(DOMString selectors),说明了匹配的算法
  • W3C Selector API 2又追加了find和findAll,但目前在各大浏览器里暂无实现(这个标准目前还未进入recommendation)。
  • WHATWG DOM 将querySelector及querySelectorAll定义在了interface ParentNode并声明Document, DocumentFragment及Element均需实现这个interface,原型为Element? querySelector(DOMString selectors)与[NewObject] NodeList querySelectorAll(DOMString selectors),并定义了scope-match的步骤。注意interface ParentNode还有用于获取相对位置的元素的两个方法query和queryAll,但目前在各大浏览器里暂无实现。
  • DOM4也新增了interface ParentNode,和WHATWG类似

注意点

  • 标准里强调了querySelectorAll返回的一定是一个static NodeList -- 也就是说如果将它的返回结果保存下来,当文档更新时,保存的NodeList里的元素不会跟着更新。
  • W3C Selector API Level 1 规定当传入的CSS选择器不合法时,会抛出SYNTAX_ERR异常。Selector API Level 2 和 WHATWG 改为了 SyntaxError。
  • 按照W3C Selector API Level 1的提示,在选择器里使用pseudo-elements(目前只有:after,:before,:first-letter,:first-line,:selection)将不会匹配到任何元素,另外出于保护隐私的考虑,标准也推荐将所有链接视为未访问,即:visited不会匹配到任何元素。
  • 无匹配元素时,querySelector返回null,querySelectorAll返回空的NodeList
  • 有多个匹配元素时,querySelector返回按照document order(先序DFS)遍历到的第一个元素,querySelectorAll返回按照 document order 排序的NodeList

兼容性

IE 9+及其他浏览器的现行版本正常支持包括CSS3的选择器,IE8支持简单的 CSS2 选择器(如:不支持空格表示的后代)

WebKit 代码分析

ContainerNode 就是 WHATWG 里描述的 interface ParentNode,ContainerNode的querySelector和querySelctorAll实际上分别调用SelectorQuery的queryFirst和queryAll(参考WebCore/dom/ContainerNode.cpp),它们又分别调用SelectorDataList的queryFirst和queryAll(注意这里的 queryAll 和标准里定义的不是一个东西。另外 SingleElementExtractorSelectorQueryTrait和AllElementExtractorSelectorQueryTrait这两个使用模版达到类似动态类型的写法挺有趣的),通过execute来对ContainerNode的子节点匹配CSS。execute里就是CSS选择器的代码,里面还有相当一部分 JIT 的优化,这里就不展开分析了。

在queryFirst用于SelectorQueryTrait的 template specialiation 的 SingleElementExtractorSelectorQueryTrait里,shouldOnlyMatchFirstElement设为true,注意execute用于匹配CSS的其他方法基本都会在第一次找到匹配元素的时候检查shouldOnlyMatchFirstElement确定是否立刻保存匹配结果并返回(使用elementDescendants达到先序DFS,elementDescendants最终也是和getElementsByID的实现一样使用到了NodeTraversal),这样就达到了标准里提到的返回先序DFS遇到的第一个匹配元素的要求。而queryAll使用了StaticElementList(StaticNodeList),来为保存匹配元素的Vector(属于WTF)创建一个 static 的快照用于返回(参见WebCore/dom/SelectorQuery.cpp)

NCZ的博客上讨论了为何StaticNodeList会相对慢很多(不过上面用的是几年前的代码,现在的代码用的是WTF的Vector的swap(底层调用std::swap)通过交换元素来实现复制,参见Source/WTF/wtf/Vector.h)

jQuery也有一个关于querySelectorAll性能问题的 Open issue。

跟随标准与Webkit源码探究DOM -- 获取元素之querySelector,querySelectorAll的更多相关文章

  1. 跟随标准与Webkit源码探究DOM -- 获取元素之getElementsByClassName

    按照类名获取元素 -- getElementsByClassName(HTML5) 标准 WHATWG 在Document与Element上均有定义,原型 HTMLCollection getElem ...

  2. 跟随标准与Webkit源码探究DOM -- 获取元素之getElementsByTagName

    按照标签名获取元素 -- getElementsByTagName 标准 DOM 1在Element和Document两个interface中均有定义,原型NodeList getElementsBy ...

  3. 跟随标准与Webkit源码探究DOM -- 获取元素之getElementById

    按照ID获取元素 -- getElementById 标准 DOM 1,定义在HTMLDocument Interface 中,原型Element getElementById(in DOMStrin ...

  4. 跟随标准与Webkit源码探究DOM -- 获取元素之getElementsByName

    按照name属性获取多元素 -- getElementsByName 标准 DOM 1 定义在HTMLDocument Interface 中,原型NodeList getElementsByName ...

  5. ConcurrentHashMap源码探究 (JDK 1.8)

    很早就知道在多线程环境中,HashMap不安全,应该使用ConcurrentHashMap等并发安全的容器代替,对于ConcurrentHashMap也有一定的了解,但是由于没有深入到源码层面,很多理 ...

  6. Vue源码探究-虚拟DOM的渲染

    Vue源码探究-虚拟DOM的渲染 在虚拟节点的实现一篇中,除了知道了 VNode 类的实现之外,还简要地整理了一下DOM渲染的路径.在这一篇中,主要来分析一下两条路径的具体实现代码. 按照创建 Vue ...

  7. Vue源码探究-全局API

    Vue源码探究-全局API 本篇代码位于vue/src/core/global-api/ Vue暴露了一些全局API来强化功能开发,API的使用示例官网上都有说明,无需多言.这里主要来看一下全局API ...

  8. Vue源码探究-事件系统

    Vue源码探究-事件系统 本篇代码位于vue/src/core/instance/events.js 紧跟着生命周期之后的就是继续初始化事件相关的属性和方法.整个事件系统的代码相对其他模块来说非常简短 ...

  9. Vue源码探究-状态初始化

    Vue源码探究-状态初始化 Vue源码探究-源码文件组织 Vue源码探究-虚拟DOM的渲染 本篇代码位于vue/src/core/instance/state.js 继续随着核心类的初始化展开探索其他 ...

随机推荐

  1. [自娱自乐] 2、超声波测距模块DIY笔记(二)

    前言 上一节我们已经大致浏览下目前销售的超声波测距模块同时设计了自己的分析电路,这次由于我买的电子元件都到了,所以就动手实验了下!至写该笔记时已经设计出超声波接收模块和超声波发射模块,同时存在超声波发 ...

  2. [游戏模版11] Win32 动画 时间消息

    >_<:This time we will study a new way to operate your picture.That is running your picture by ...

  3. jquery简单笔记(1) - 基础记录

    一.dom对象及jquery对象相互转换 jquery对象转换成dom对象,即 [index] 和 get(index) 第一种方式: var $j = $('#id'); // jquery对象 v ...

  4. CheckStyle, 强制你遵循编码规范

    如今代码静态检查越来越重要,已经成为构建高质量软件的不可或缺的一个验证步骤.如果你使用的是java语言,那么CheckStyle则是一个利器. CheckStyle能够帮助程序员检查代码是否符合制定的 ...

  5. APU平台DirectX 12性能测试:超级大惊喜!

    APU平台DirectX 12性能测试:超级大惊喜! 转自:http://www.ithome.com/html/digi/129840.htm [size=1pc]微软将会在接下来的GDC 2015 ...

  6. 使用TabBarController(代码实现)

    step01:使用Xcode创建一个项目 step02:填写项目必要信息 step03:检查文件结构树是否正确 step04:创建一些类,这些类将会在后面用到!(选择Swift File) step0 ...

  7. 01_JavaScript简介

    js用途 前端三层 结构层 HTML 从主义角度描述页面的结构 样式层 CSS 从审美的角度装饰页面 行为层 JS 从交互角度提升体验 HTML 里面的 b(加粗)/i(倾斜)/u(下划线)等标签由于 ...

  8. 关于eclipse android 在manifest改app应用包名注意事项

    在我刚学android 时候,然后立即就做项目.那时连eclipse 使用都不是很熟练.很多功能都不知道.新手如果这时去改app应用的包名,没有改好会变成所有控件在R文件里面id都找不到. 先上两张图 ...

  9. [原创]配置管理技术圈QQ群:129489184

    [原创]配置管理技术圈QQ群:129489184 配置管理技术圈QQ群:129489184,研究cvs,svn,git,cc等平台配置技术,涉及版本控制,持续集成,自动化构建等! 欢迎各位同学来,来时 ...

  10. JavaMail发送邮件时判断发送结果1.5.x

    经常有用户在平台乱注册帐号,系统得自动清理.现在要判断一下邮件是否正确少了很多垃圾注册用户了. 测试 http://sms.reyo.cn/user/register 感谢您的反溃信息!!! 程序代码 ...