Sizzle.selectors.relative 源碼分析!

來源:互聯網
上載者:User

標籤:sizzle   jquery   javascript   源碼   

1 jQuery 對象Sizzle.selectors.relative中存放了塊間關係符和對應的塊間關係過濾函數,稱為“塊間關係過濾函數集”

   塊間關係符共有4種,其含義和過濾方式。

 

在函數Sizzle( selector, context, results, seed )從右向左進行過濾時,塊間關係過濾函數被
調用,用於檢查映射集checkSet中的元素是否匹配塊間關係符左側的塊運算式。調用時的參
數格式為:

Sizzle.selectors.relative[ 塊間關係符 cur  ](  映射集 checkSet,  左側塊運算式pop, contextXML );

塊間關係過濾函數接受3個參數:
‰ ‰參數checkSet:映射集,對該元素集合執行過濾操作。
‰ ‰參數part:大多數情況下是塊間關係符左側的塊運算式,該參數也可以是DOM元素。
‰ ‰參數isXML:布爾值,指示是否運行在一個XML文檔中。
塊間關係過濾函數實現的3個關鍵步驟如下:
1)遍曆映射集checkSet。
2)按照塊間關係符尋找每個元素的兄弟元素、父元素或祖先元素。
3)檢尋找到的元素是否匹配參數part,並替換映射集checkSet中對應位置的元素。
a. 如果參數part是標籤,則檢尋找到的元素其節點名稱nodeName是否與之相等,
如果相等則替換為找到的元素,不相等則替換為false。
b. 如果參數part是DOM元素,則檢尋找到的元素是否與之相等,如果相等則替換
為true,不相等則替換為false。
c. 如果參數part是非標籤字串,則調用方法Sizzle.filter( selector, set, inplace, not )過濾。
也就是說,遍曆結束後,映射集checkSet中的元素可能會是兄弟元素、父元素、
祖先元素、true或false。


1 塊間關係符"+"匹配選取器"prev + next",即匹配所有緊接在元素prev後的兄弟元素
next。例如,$("div + span")、$(".lastdiv + span")。對於從右向左的尋找方式,則是檢查元
素next之前的兄弟元素是否匹配塊運算式prev。

var Expr = Sizzle.selectors = {relative: {"+": function(checkSet, part){//檢查參數是否為字串var isPartStr = typeof part === "string",//指示參數part是否為標籤字串isTag = isPartStr && !rNonWord.test( part ),//isPartStrNotTag:指示參數part是否是非標籤字串。isPartStrNotTag = isPartStr && !isTag;if ( isTag ) {part = part.toLowerCase();}/*遍曆映射集checkSet,尋找每個元素的前一個兄弟元素,並替換映射集checkSet中對應位置的元素,有以下3個邏輯分支:?1 如果未找到兄弟元素,則替換為false。2 ?如果找到了兄弟元素,並且參數part是標籤,則檢查兄弟元素的節點名稱nodeName是否與之相等,如果相等則替換為兄弟元素,不相等則替換為false。3 ?如果找到了兄弟元素,並且參數part是DOM元素,則檢查二者是否相等,如果相等則替換為true,不相等則替換為false。因此,在遍曆結束後,映射集checkSet中的元素可能會是兄弟元素、true或false。*/for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {if ( (elem = checkSet[i]) ) {/*在遍曆兄弟元素的同時過濾掉非元素節點,並且只要取到一個兄弟元素就退出while迴圈。*/while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?elem || false :elem === part; }}/*如果參數part是非標籤字串,則調用方法Sizzle.filter( selector, set, inplace, not )過濾映射集checkSet。對於參數part是標籤和DOM元素的情況,在前面遍曆映射集checkSet時已經處理過了。*/if ( isPartStrNotTag ) {Sizzle.filter( part, checkSet, true );}},},};

2 塊間關係符">"用於選取器"parent > child",即匹配父元素parent下的子項目child。
例如,$("div + span")、$(".lastdiv + span")。對於從右向左的尋找方式,則是檢查子項目
child的父元素是否匹配塊運算式parent。


var Expr = Sizzle.selectors = {relative: {">": function( checkSet, part ) {var elem,isPartStr = typeof part === "string",i = 0,l = checkSet.length;/*如果參數part是標籤,則遍曆映射集checkSet,尋找每個元素的父元素,並檢查父元素的節點名稱nodeName是否與參數part相等,如果相等則替換映射集checkSet中對應位置的元素為父元素,不相等則替換為false。 */if ( isPartStr && !rNonWord.test( part ) ) {part = part.toLowerCase();for ( ; i < l; i++ ) {elem = checkSet[i];if ( elem ) {var parent = elem.parentNode;checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;}}} else {/*如果參數part不是標籤,則可能是非標籤字串或DOM元素,同樣遍曆映射集checkSet,尋找每個元素的父元素,並替換映射集checkSet中對應位置的元素,在這個過程中有以下2個邏輯分支:?1 ?如果參數part是非標籤字串,則在遍曆映射集checkSet的過程中,替換映射集checkSet中對應位置的元素為父元素,遍曆結束後調用方法Sizzle.filter( selector, set, inplace, not )過濾映射集checkSet。?2 ?如果參數part是元素,則在遍曆映射集checkSet時,檢查每個元素的父元素是否與之相等,如果相等則替換映射集checkSet中對應位置的元素為true,不相等則替換為false。因此,在遍曆結束後,映射集checkSet中的元素可能會是父親元素、true或false。*/for ( ; i < l; i++ ) {elem = checkSet[i];if ( elem ) {checkSet[i] = isPartStr ?elem.parentNode :elem.parentNode === part;}}if ( isPartStr ) {Sizzle.filter( part, checkSet, true );}}},},};


3 塊間關係符""用於選取器"ancestor descendant",即匹配祖先元素ancestor的所有後代
元素descendant。例如,$("div button")、$("div .btn")。對於從右向左的尋找方式,則是檢
查後代元素descendant的祖先元素是否匹配塊運算式ancestor。
var Expr = Sizzle.selectors = {relative: {"": function(checkSet, part, isXML){var nodeCheck,doneName = done++,checkFn = dirCheck;/*?1 如果參數part是非標籤字串或DOM元素,則調用函數dirCheck()過濾映射集checkSet。?2 如果參數part是標籤,則調用函數dirNodeCheck()過濾映射集checkSet。調用函數dirCheck()和dirNodeCheck()時的參數格式為:checkFn( 方向 "parentNode/previousSibling", 塊運算式 part, 緩衝計數器 doneName, 映射集 checkSet, nodeCheck, isXML )函數dirCheck()和dirNodeCheck()會遍曆映射集checkSet,尋找每個元素的祖先元素,並檢查是否有祖先元素匹配參數part,同時替換映射集checkSet中對應位置的元素。*/if ( typeof part === "string" && !rNonWord.test( part ) ) {part = part.toLowerCase();nodeCheck = part;checkFn = dirNodeCheck;}checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );},},};


4 塊間關係符"~"用於選取器"prev~siblings",即匹配元素prev之後的所有兄弟元
素siblings。例如,$(‘div~p‘)。對於從右向左的尋找方式,則是檢查元素siblings之前的
兄弟元素是否匹配塊運算式prev。
Sizzle.selectors.relative["~"]( checkSet, part )的源碼實現與Sizzle.selectors.relative[""]
( checkSet, part )幾乎一樣,兩者的區別僅僅在於調用函數dirCheck()和dirNodeCheck()時第
一個參數的值不同,前者是"previousSibling",後者則是"parentNode"。
相關代碼如下所示:

var Expr = Sizzle.selectors = {relative: {"~": function( checkSet, part, isXML ) {var nodeCheck,doneName = done++,checkFn = dirCheck;if ( typeof part === "string" && !rNonWord.test( part ) ) {part = part.toLowerCase();nodeCheck = part;checkFn = dirNodeCheck;}checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );}},};


Sizzle.selectors.relative 源碼分析!

聯繫我們

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