javascript 選取器簡明教程

來源:互聯網
上載者:User
文章目錄
  • 兄長選擇符
  • 相鄰選擇符
  • 親子選擇符

本來準備開講jQuery源碼學習筆記六的,但心中有佛才能看到佛,有些人連選取器都不知什麼東西,直接講下去,估計有人會看得雲裡霧裡,滿頭霧水了。加之,John Resig有一種把代碼寫得不知所云的魔力,他擁有強大的馭駕代碼的實力,他自己看當然沒問題,其他人則要命了。常常是一句代碼調用幾個方法,每個方法相隔幾十行甚至上百行,而且這些方法還常常是幌子,真正做事是其他代碼。這樣盤根錯節的代碼與Base2有得一拼。最後,選取器本身也是非常複雜的東西,有必須獨立提出來說一下。

選取器其實早已實現,不過都是一些不起眼但超常用的方法:getElementById,getElementsByName,getElementsByTagName。但外國人不滿意這些API,於是搞出了getElementsByClassName,進而是getElementsBySelector,支援當時已公布的所有CSS2.1選擇符!然後Prototype用一個$與一個$$把它們統括起來。之所以這樣,其動機顯然易見,如果返回一個就不用索引號去取了!像jQuery那樣無論是返回多少個,反正都包裹在jQuery對象,都要用索引號或get方法把真正DOM元素取出來,因此用不用$$都差不多,於是$統一天下!

但這個包打天下的選取器其實包括多少東西呢?細算一下,ID選取器,標籤選取器,聯合選取器,屬性選取器,關係選取器與偽類別選取器。ID選取器,就是以#開頭的,標籤選取器就是tagName,聯合選取器就是那個逗號,屬性選取器就是用中括弧括起來的欄位,裡面也非常複雜,可以單純只有屬性名稱,不用屬性值,如果有屬性值,又分好幾種情況匹配(詳見我的另一篇博文《getElementsByAttribute》)。像getElementsByName應該歸併於屬性選取器,因為name也是一個屬性。關係選擇符又細分為四個:兄長(~),親子(>),相鄰(+)與後代(空格)。偽類別選取器的成員非常龐大,因為CSS3新添加的這些偽類選擇符也是如此。除了虛擬元素選擇符與頁面偽類與連結偽類等少量無法轉換為選取器外,其他基本都能。這些符合資格的偽類有目標偽類,結構偽類,語言偽類與UI狀態偽類。語言偽類與UI狀態偽類與屬性選擇符很相近,因此實現手段也一致。目標偽類我們可以通過截取地址欄上的參數,用IE選取器搞定。結構偽類則又是個大家族,分為兩派:root與其他。:root就是根節點documentElement。其他都可以統稱這子項目過濾器,我們可以根據順序(nth-child)來篩選,可以根據類型來選(only-of-type),又可以組合類別型與順序來選,還可以根據元素裡面有沒有內容來選(empty),裡面還有一些變種,如那些帶first與last的。在jQuery,為了照顧那些美工MM,John Resig又定義許多快捷的選擇符,這個,自己看文檔吧。

兄長選擇符

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>兄長選取器</title></p><p> <style type="text/css"><br /> span ~ strong {<br /> background:red;<br /> }<br /> </style><br /> <script type="text/javascript" charset="utf-8"></p><p> </script><br /> </head><br /> <body><br /> <pre><br /> span ~ strong {<br /> background:red;<br /> }<br /> </pre><br /> <p><span>span</span><strong>strong</strong><strong>strong</strong><span>444</span><b>b</b><strong>strong</strong></p></p><p> </body><br /></html><br />

運行代碼

相鄰選擇符

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>相鄰選取器</title></p><p> <style type="text/css"><br /> span + strong {<br /> background:red;<br /> }<br /> </style><br /> <script type="text/javascript" charset="utf-8"></p><p> </script><br /> </head><br /> <body><br /> <pre><br /> span + strong {<br /> background:red;<br /> }<br /> </pre><br /> <p><span>span</span><strong>strong</strong><strong>strong</strong><span>444</span><b>b</b><strong>strong</strong></p></p><p> </body><br /></html><br />

運行代碼

親子選擇符

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>親子選取器</title></p><p> <style type="text/css"><br /> p > strong {<br /> background:red;<br /> }<br /> p > [ss] {<br /> background: DodgerBlue;<br /> }<br /> </style><br /> <script type="text/javascript" charset="utf-8"></p><p> </script><br /> </head><br /> <body><br /> <pre><br /> p > strong {<br /> background:red;<br /> }<br /> p > [ss] {<br /> background: DodgerBlue;<br /> }<br /> </pre><br /> <p><span ss="nasami">span</span><strong>strong</strong><strong>strong</strong><span>444</span><b>b</b><strong>strong</strong></p></p><p> </body><br /></html><br />

運行代碼

好了,我們說一下它的實現原理吧。通常都是選擇一個字串,最後返回一組元素。如果字串是“#aaa”就好辦,把前面的"#"
砍掉,用getElementsById去尋找便是!如果是"p span"意思是取得所有p元素中的span元素,我們先用document.getElementsByTagName("p")得到所有p元素,然後遍曆裡面的p,用currentP.getElementsByTagName("span")就行了。但這都是最理想的情況下,我們要怎樣才知道調用這些API呢?#提醒我們用IE選取器,但如果#號是包含在引號中呢,如p["gh#erewf"],這裡也有#號。因此我們必須處理一下字串,如把兩邊的空白去掉,把裡面不必要的空白去掉,裡面的每個空白只佔一個字元空間就是,讓我們知道那些後代選擇符就是,多餘的沒有必要。我們看jQuery是如何處理的:

<br /> //一個很長的選擇符<br /> var str = " #div , h1#id\<br /> dd.class > span[dd='22222 > 3233'] ul+ li, .class:contain(\"你的+ 999\"),strong span ";<br /> var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g;<br /> var a = str.match(chunker);<br /> alert(a)<br />

運行代碼

一個很強大的正則,不過這樣後代選擇符就看不到了,jQuery在後面一定做了什麼補救措施。事實上,jQuery許多東西都不是一步到位,一個方法調用另一個方法,最後不是怎的就解決了其實一下子轉換為數組意義不大,後面還是要其他正則進行深加工,它們都需要進一步的正則匹配,分析當前的數組元素是ID選擇符還是屬性選擇符。

看來大家喜歡jQuery,那我就舉jQuery吧。其他類庫也是用許多正則來處理字串,來得到它們想要的資訊。jQuery外面看起來很漂亮很清致,裡面的實現真是相當複雜與噁心。或許John Resig是個心理陰暗的人,他公開源碼但不想別人看懂,故意寫成這個樣子。我更懷疑源碼中那些注釋是給jQuery另兩個作者看的……嘛,都瞎猜的。我們接著看實現流程,上面這些ID,class,name,attr什麼的,基本上是用那兩個選取器document.getElementById與element.getElementsByTagName加getAttribute搞定。猶其是那個標籤選取器,每個元素節點都有這方法,我們才可以層層遴選正確的元素。每次我們取得一堆元素,然後逐一檢測其屬性與在父元素的位置,得到結果放到一個數組中,然後下一次再重複這樣的步驟。有時,兩個元素都有相同的子項目,我們就需要在這些元素做一些標記,如果沒有這標記的才放進數組,有就跳過。至於這些怎樣實現,這是jQuery源碼要講的。最後附上一個表:

開頭字元 代表選擇符 判斷方法
# ID選擇符 /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/
. 類選擇符 /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/
後代選擇符 /^\s\s*/
[ 屬性選擇符 /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/
+ 相鄰選擇符 /^[>\+\~]/
~ 兄長選擇符 /^[>\+\~]/
> 親子選擇符 /^[>\+\~]/
: 偽類選擇符 /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
, 聯合選擇符 /,/
字母 標籤選擇符 /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.