zoukankan      html  css  js  c++  java
  • 跟随标准与Webkit源码探究DOM -- 获取元素之querySelector,querySelectorAll

    使用CSS选择器获取元素 -- querySelectorquerySelectorAll(HTML5)

    标准

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

    注意点

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

    兼容性

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

    WebKit 代码分析

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

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

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

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

  • 相关阅读:
    删除字符串组中相同元素,并删除值为空的元素 (转载,笔记)
    获取操作系统语言
    .net 传递中文参数解决办法
    古怪问题:vs2003程序 在繁体平台下控件位置发生变化
    Godaddy邮箱C#发送邮件设置
    无法显示隐藏文件的解决方法
    虚拟机文件
    sql 2000 修复问题
    看QQ是否在线
    sql 知识摘录
  • 原文地址:https://www.cnblogs.com/joyeecheung/p/4122959.html
Copyright © 2011-2022 走看看