jQuery源碼分析-04 選擇器-Sizzle-工作原理分析
更新時間:2011年11月14日 23:47:26 作者:
在分析Sizzle源碼之前,先整理一下選擇器的工作原理,先明確一些選擇器中用到的名詞,后邊閱讀時不會有歧義
作者:nuysoft/高云 QQ:47214707 EMail:nuysoft@gmail.com
聲明:本文為原創(chuàng)文章,如需轉(zhuǎn)載,請注明來源并保留原文鏈接。
在分析Sizzle源碼之前,先整理一下選擇器的工作原理
先明確一些選擇器中用到的名詞,后邊閱讀時不會有歧義:
選擇器表達式: "div > p"
塊表達式: "div" "p"
并列選擇器表達式: "div, p"
塊分割器: Sizzle中的chunker正則,對選擇器表達式從左向右分割出一個個塊表達式
查找器: 對塊表達式進行查找,找到的DOM元素數(shù)組叫候選集
過濾器: 對塊表達式和候選集進行過濾
關系過濾器 對塊表達式之間的關系進行過濾,共有四種關系:"+" 緊挨著的兄弟關系;">" 父子關系;"" 祖先關系;"~" 之后的所有兄弟關系
候選集: 查找器的結(jié)果,待過濾器進行過濾
映射集: 候選集的副本,過濾器和關系過濾器對映射集進行過濾
工作流程:
1. 使用塊分割器對選擇器表達式進行分割,從左向右
如果遇到用逗號","分割的并列選擇器表達式,只分割至第一個逗號前邊的選擇器表達式1,將剩余部分記錄下來
2. 對最后一個塊表達式進行查找Sizzle.find,結(jié)果放入候選集set,并將塊表達式中匹配的字符串部分刪除
查找器Sizzle.find從正則集Expr.match獲取對應的正則表達式,對塊表達式進行匹配,匹配成功則從查找函數(shù)集Expr.find獲取對應的查找函數(shù)執(zhí)行
查找順序定義在Expr.order中,依次是:ID CLASS NAME TAG,查找時CLASS需要瀏覽器支持getElementsByClassName
Expr.match中設定了ID CLASS NAME ATTR TAG CHILD POS PSEUDO的正則匹配表達式
3. 如果最后一個塊表達式不為空(字符串),過濾器Sizzle.filter對set進行過濾
過濾器Sizzle.filter僅對單個塊表達式起作用,僅對候選集set中的元素起作用,檢查候選集set中的元素滿足剩余的塊表達式
在過濾器Sizzle.filter的過濾過程中,不符合條件的被設置為false,符合條件的不做修改
過濾時從正則集Expr.leftMatch獲取對應的正則表達式,對塊表達式進行匹配,匹配成功則從Expr.filter獲取對應的過濾函數(shù)執(zhí)行
Expr.leftMatch定義了與Expr.match同樣數(shù)量的正則表達式:ID CLASS NAME ATTR TAG CHILD POS PSEUDO
過濾函數(shù)集Expr.filter定義了PSEUDO CHILD ID TAG CLASS ATTR POS的過濾函數(shù)
過濾器Sizzle.filter進行過濾之前,會先調(diào)用預過濾器Expr.preFilter對過濾所需的參數(shù)進行修正,但是CLASS是個例外
在CLASS進行預過濾時做了優(yōu)化,直接將匹配class的元素作為候選集返回,縮小過濾范圍,縮小候選集范圍
將以上查找和過濾得到候選集set復制,放入映射集checkSet,后邊的過濾操作在checkSet上進行
對最后一個塊表達式的查找和過濾到這里結(jié)束,得到一個候選集set和映射集checkSet
4. 在映射集checkSet上將剩余的塊表達式從右向左進行過濾,根據(jù)與前一個塊表達式的關系,從關系過濾器集Expr.relative中獲取對應的函數(shù)執(zhí)行關系過濾
在關系過濾器Expr.relative的過濾過程中,不符合條件的被設置為false,符合條件的則被設置為父元素、祖先元素、兄長元素
元素之間的關系共有四種:"+" 緊挨著的兄弟關系;">" 父子關系;"" 祖先關系;"~" 之后的所有兄弟關系
在關系過濾器Expr.relative的過濾過程中,如果遇到塊表達式是標簽TAG的情況,則直接比較標簽類型nodeName是否相等
如果不是標簽TAG的情況,則會調(diào)用過濾器Sizzle.filter進行過濾,過濾過程見第3步
從右向左過濾,直到所有塊表達式全部過濾完
5. 根據(jù)過濾后的映射集checkSet,從候選集set中挑選最終的結(jié)果集,在映射集checkSet中
如果是null、false,將被過濾
如果不是Element(nodeType===1),將被過濾
如果上下文不是Document而是某個Element,不是Element的子元素的,將被過濾
6. 如果存在并列表達式,重復1~5,并將得到的最終結(jié)果集合并、排序、去重
如果僅有一個選擇器表達式,沒有并列選擇器表達式,不需要排序
以下過程不屬于Sizzle,屬于jQuery對Sizzle的擴展
7. 如果存在多個上下文,對每個上下文重復1~6
多個上下文例子:$('div').find('div > p'),$('div')可能找到多個div
其實第7步是jQuery選擇器的入口,從第7步去調(diào)用1~6,調(diào)用時傳入一個空的jQuery對象作為結(jié)果集
默認以document為上下文:(context || rootjQuery).find( selector )
8. 將從多個上下文找到的結(jié)果集合并、去重,返回結(jié)果集
done!
聲明:本文為原創(chuàng)文章,如需轉(zhuǎn)載,請注明來源并保留原文鏈接。
在分析Sizzle源碼之前,先整理一下選擇器的工作原理
先明確一些選擇器中用到的名詞,后邊閱讀時不會有歧義:
選擇器表達式: "div > p"
塊表達式: "div" "p"
并列選擇器表達式: "div, p"
塊分割器: Sizzle中的chunker正則,對選擇器表達式從左向右分割出一個個塊表達式
查找器: 對塊表達式進行查找,找到的DOM元素數(shù)組叫候選集
過濾器: 對塊表達式和候選集進行過濾
關系過濾器 對塊表達式之間的關系進行過濾,共有四種關系:"+" 緊挨著的兄弟關系;">" 父子關系;"" 祖先關系;"~" 之后的所有兄弟關系
候選集: 查找器的結(jié)果,待過濾器進行過濾
映射集: 候選集的副本,過濾器和關系過濾器對映射集進行過濾
工作流程:
1. 使用塊分割器對選擇器表達式進行分割,從左向右
如果遇到用逗號","分割的并列選擇器表達式,只分割至第一個逗號前邊的選擇器表達式1,將剩余部分記錄下來
2. 對最后一個塊表達式進行查找Sizzle.find,結(jié)果放入候選集set,并將塊表達式中匹配的字符串部分刪除
查找器Sizzle.find從正則集Expr.match獲取對應的正則表達式,對塊表達式進行匹配,匹配成功則從查找函數(shù)集Expr.find獲取對應的查找函數(shù)執(zhí)行
查找順序定義在Expr.order中,依次是:ID CLASS NAME TAG,查找時CLASS需要瀏覽器支持getElementsByClassName
Expr.match中設定了ID CLASS NAME ATTR TAG CHILD POS PSEUDO的正則匹配表達式
3. 如果最后一個塊表達式不為空(字符串),過濾器Sizzle.filter對set進行過濾
過濾器Sizzle.filter僅對單個塊表達式起作用,僅對候選集set中的元素起作用,檢查候選集set中的元素滿足剩余的塊表達式
在過濾器Sizzle.filter的過濾過程中,不符合條件的被設置為false,符合條件的不做修改
過濾時從正則集Expr.leftMatch獲取對應的正則表達式,對塊表達式進行匹配,匹配成功則從Expr.filter獲取對應的過濾函數(shù)執(zhí)行
Expr.leftMatch定義了與Expr.match同樣數(shù)量的正則表達式:ID CLASS NAME ATTR TAG CHILD POS PSEUDO
過濾函數(shù)集Expr.filter定義了PSEUDO CHILD ID TAG CLASS ATTR POS的過濾函數(shù)
過濾器Sizzle.filter進行過濾之前,會先調(diào)用預過濾器Expr.preFilter對過濾所需的參數(shù)進行修正,但是CLASS是個例外
在CLASS進行預過濾時做了優(yōu)化,直接將匹配class的元素作為候選集返回,縮小過濾范圍,縮小候選集范圍
將以上查找和過濾得到候選集set復制,放入映射集checkSet,后邊的過濾操作在checkSet上進行
對最后一個塊表達式的查找和過濾到這里結(jié)束,得到一個候選集set和映射集checkSet
4. 在映射集checkSet上將剩余的塊表達式從右向左進行過濾,根據(jù)與前一個塊表達式的關系,從關系過濾器集Expr.relative中獲取對應的函數(shù)執(zhí)行關系過濾
在關系過濾器Expr.relative的過濾過程中,不符合條件的被設置為false,符合條件的則被設置為父元素、祖先元素、兄長元素
元素之間的關系共有四種:"+" 緊挨著的兄弟關系;">" 父子關系;"" 祖先關系;"~" 之后的所有兄弟關系
在關系過濾器Expr.relative的過濾過程中,如果遇到塊表達式是標簽TAG的情況,則直接比較標簽類型nodeName是否相等
如果不是標簽TAG的情況,則會調(diào)用過濾器Sizzle.filter進行過濾,過濾過程見第3步
從右向左過濾,直到所有塊表達式全部過濾完
5. 根據(jù)過濾后的映射集checkSet,從候選集set中挑選最終的結(jié)果集,在映射集checkSet中
如果是null、false,將被過濾
如果不是Element(nodeType===1),將被過濾
如果上下文不是Document而是某個Element,不是Element的子元素的,將被過濾
6. 如果存在并列表達式,重復1~5,并將得到的最終結(jié)果集合并、排序、去重
如果僅有一個選擇器表達式,沒有并列選擇器表達式,不需要排序
以下過程不屬于Sizzle,屬于jQuery對Sizzle的擴展
7. 如果存在多個上下文,對每個上下文重復1~6
多個上下文例子:$('div').find('div > p'),$('div')可能找到多個div
其實第7步是jQuery選擇器的入口,從第7步去調(diào)用1~6,調(diào)用時傳入一個空的jQuery對象作為結(jié)果集
默認以document為上下文:(context || rootjQuery).find( selector )
8. 將從多個上下文找到的結(jié)果集合并、去重,返回結(jié)果集
done!
相關文章
jquery實現(xiàn)很酷的網(wǎng)頁頂部圖標下拉菜單效果
這篇文章主要介紹了jquery實現(xiàn)很酷的網(wǎng)頁頂部圖標下拉菜單效果,效果非常美觀大方,通過鼠標hover事件及頁面元素的遍歷與樣式操作實現(xiàn)該功能,需要的朋友可以參考下2015-08-08
jQuery插件實現(xiàn)非常實用的tab欄切換功能【案例】
這篇文章主要介紹了jQuery插件實現(xiàn)非常實用的tab欄切換功能,涉及jQuery事件響應及頁面元素屬性動態(tài)操作相關實現(xiàn)技巧,需要的朋友可以參考下2019-02-02
jquery.Jwin.js 基于jquery的彈出層插件代碼
測試頁面需要引用jquery的js文件 插件文件jquery.Jwin.js jquery.Jwin插件的使用參數(shù)都有詳細說明2012-05-05
JQuery擴展插件Validate 3通過參數(shù)設置錯誤信息
最終顯示在頁面上的錯誤分為兩種:第一種是默認錯誤信息,該信息已經(jīng)被定義在插件中了,可以手動修改。2011-09-09

