跟隨標準與Webkit源碼探究DOM -- 擷取元素之querySelector,querySelectorAll

來源:互聯網
上載者:User

標籤:des   blog   http   io   ar   使用   sp   for   on   

使用CSS選取器擷取元素 -- querySelectorquerySelectorAll(HTML5)標準
  • W3C Selector API Level 1為DocumentDocumentFragmentElement追加了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 2 和 WHATWG 改為了 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(注意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。

跟隨標準與Webkit源碼探究DOM -- 擷取元素之querySelector,querySelectorAll

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.