天天看點

jQuery技術内幕:深入解析jQuery架構設計與實作原理. 3.6 Sizzle.find( expr, context, isXML )

<b>3.6 sizzle.find( expr,</b>

context, isxml )

方法sizzle.find( expr, context, isxml )負責查找與塊表達式比對的元素集合。該方法會按照表達式類型數組sizzle.selectors.order規定的查找順序(id、class、name、tag)逐個嘗試查找,如果未找到,則查找上下文的所有後代元素(*)。

圖3-3 sizzle( selector, context, results, seed )的執行過程

方法sizzle.find( expr, context, isxml )執行的5個關鍵步驟如下:

1)先用正則集合sizzle.selectors.leftmatch中的正則确定表達式類型。

2)然後調用查找函數集sizzle.selectors.find中對應類型的查找函數,查找比對的元素集合。

3)然後删除塊表達式中已查找過的部分。

4)如果沒有找到對應類型的查找函數,則讀取上下文的所有後代元素。

5)最後傳回格式為{set:候選集, expr:塊表達式剩餘部分}的對象。

下面來看看該方法的源碼實作。

1.?定義sizzle.find( expr,

相關代碼如下所示:

4051 sizzle.find = function( expr, context,

isxml ) {

第4051行:定義方法sizzle.find( expr, context, isxml ),它接受3個參數:

參數expr:塊表達式。

參數context:dom元素或文檔對象,作為查找時的上下文。

參數isxml:布爾值,訓示是否運作在一個xml文檔中。

2.?周遊表達式類型數組sizzle.selectors.order

4052    

var set, i, len, match, type, left;

4053

4054    

if ( !expr ) {

4055        

return [];

4056    

}

4057

4058    

for ( i = 0, len = expr.order.length; i &lt; len; i++ ) {

4059        

type = expr.order[i];

4060        

第4054~4056行:如果塊表達式expr是空字元串,則直接傳回空數組[]。

第4058行:表達式類型數組sizzle.selectors.order中定義了查找單個塊表達式時的順序,依次是id、class、name、tag,其中,class需要浏覽器支援方法getelements

byclassname()。關于sizzle.selectors.order的具體說明請參見3.9.1節。

(1)确定塊表達式類型sizzle.selectors.leftmatch[ type ]

4061        

if ( (match = expr.leftmatch[ type ].exec( expr )) ) {

4062             left = match[1];

4063             match.splice( 1, 1 );

4064

第4061行:檢查每個表達式類型type在sizzle.selectors.leftmatch中對應的正則是否比對塊表達式expr,如果比對,則可以确定塊表達式的類型。

第4062~4063行:對象sizzle.selectors.leftmatch中存放了表達式類型和正則的映射,正則可以用于确定塊表達式的類型,并解析其中的參數。它是基于對象sizzle.selectors.match初始化的,具體請參見3.9.2節。

(2)查找比對元素sizzle.selectors.find[ type ]

4065             if ( left.substr( left.length - 1

) !== "\\" ) {

4066                 match[1] = (match[1] ||

"").replace( rbackslash, "" );

4067                 set = expr.find[ type ](

match, context, isxml );

4068

第4065行:如果比對正則的内容以反斜杠"\\"開頭,表示反斜杠"\\"之後的字元被轉義了,不是期望的類型,這時會認為類型比對失敗。

第4066行:過濾其中的反斜杠,以支援将某些特殊字元(例如,“#”、“.”、“[”)作為普通字元使用。舉個例子,假設某個input元素的屬性id是"a.b",則對應的選擇器表達式應該寫作$("#a\\.b"),這裡替換掉了反斜杠,又會變回"a.b",是以仍然可以通過執行document.getelementsbyid("a.b")查找到input元素。

第4067行:調用表達式類型type在查找函數集sizzle.selectors.find中對應的查找函數,查找比對的元素集合。sizzle.selectors.find中定義了id、class、name、tag所對應的查找函數,具體請參見3.9.3節。

(3)删除塊表達式中已查找過的部分

4069                 if ( set != null ) {

4070                     expr = expr.replace(

expr.match[ type ], "" );

4071                     break;

4072                 }

4073             }

4074        

4075    

4076

第4069~4072行:如果set不是null和undefined,表示對應的查找函數執行了查找操作,則不管有沒有找到比對元素,都将塊表達式expr中已查找過的部分删除,并結束方法sizzle.find( expr, context, isxml )的查找過程。

第4070行:用對象sizzle.selectors.match中對應的正則來比對已查找過的部分,具體請參見3.9.2節。

3.?如果沒有找到對應類型的查找函數,則讀取上下文的所有後代元素

4077    

if ( !set ) {

4078        

set = typeof context.getelementsbytagname !== "undefined" ?

4079             context.getelementsbytagname(

"*" ) :

4080             [];

4081    

4082

第4077~4081行:如果set是null或undefined,(大多數情況下)表示沒有在sizzle.selectors.find中找到對應的查找函數,例如,$(":input")會讀取上下文的所有後代元素作為候選集。

4.?傳回{ set:候選集, expr:塊表達式剩餘部分}

4083    

return { set: set, expr: expr };

4084 };

方法sizzle.find( expr, context, isxml )的執行過程可總結為圖3-5。

圖3-5 sizzle.find( expr, context, isxml )的執行過程

繼續閱讀