sizzle分析記錄 分解流程

2021-09-06 17:02:43 字數 3728 閱讀 9811

js

$("form div > p[name=aaron]")
解析的流程:

編譯器:分5個步驟

涉及: tag元素 關係選擇器 屬性選擇器

1:通過tokenize詞法分析器分組

2:遍歷tokens,從右邊往左邊開始篩選,最快定位到目標元素合集

//

先看看有沒有搜尋器find,搜尋器就是瀏覽器一些原生的取dom介面,簡單的表述就是以下物件了

=

操作如下

expr.find["tag"] = support.getelementsbytagname ?

function

( tag, context )

} :

那麼第一篩選找到的定位元素,就形成了乙個 seed種子合集,那麼餘下的所有的操作都是圍繞這個種子合集處理

因為節點總是存在各種關係的,所以不管是通過這個最靠近的目標的元素,往上還是往下 都是可以處理的

3:重組選擇器,開始執行繼續分解"form div > [name=aaron]"

因為種子合已經抽出了,所以選擇器就需要重新排列

"form div > [name=aaron]"
踢掉了p元素,已經被抽離了

4 : 生成編譯處理器

這裡為什麼要這麼複雜,因為生成了編譯閉包可以快取起來,通過這種機制,增加了重複選擇器的效率

在matcherfromtokens方法中通過分解tokens生成對應的處理器

例如:form div [name=aaron]

在分解過程中分2大塊

a:關係選擇器的處理  > + ~ 空

b: attr child class id pseudo tag的處理

用matchers保留組合關係

1:分解第乙個tag:form 儲存處理器到matchers.push( expr.filter[「tag」]) ;

2:分解第二個「空」的關係選擇器,此時

a:用elementmatcher把之前的matchers壓入到這個匹配裡面,生成乙個遍歷方法的處理

function

elementmatcher( matchers )

}return

true

; } :

matchers[0];

}

b:用addcombinator再次包裝,生成乙個位置關係的查詢關係

function

addcombinator( matcher, combinator, base ) );

if ( (oldcache = outercache[ dir ]) &&oldcache[ 0 ] === dirruns && oldcache[ 1 ] ===donename )

else}}

}};}

所以此時的matchers的關係是乙個層級的包含結構,然後依次這樣遞迴

這個地方相當繞!!!!

生成的最後

cached = matcherfromtokens( match[i] );

變成了乙個超大的巢狀閉包

5: 通過matcherfromgroupmatchers這個函式來生成最終的匹配器

var byset = setmatchers.length > 0,

byelement = elementmatchers.length > 0,

supermatcher = function

(seed, context, xml, results, outermost)

return supermatcher

通過matcherfromgroupmatchers的處理最直接的就是能看出,elementmatchers, setmatchers 2個結果不需要再返回出去,直接形成curry的方法,在內部就合併引數

外面就直接呼叫了,這樣

var compilefunc = compiled ||compile( selector, match );

compilefunc(

seed,

context,

!documentishtml,

results,

outermost

);

compilefunc 一直是持有elementmatchers, setmatchers 的引用的,這個設計的手法還是值得借鑑的

執行期:

至此之前的5個步驟都是編譯成函式處理器的過程,然後就是開始執行了

粗的原理就是把直接分解出來的seed種子合集丟到這個處理器中,然後處理器就會根據各種關係進行分解匹配

從而得到結果集

supermatcher:

while ( (matcher = elementmatchers[j++]) ) 

}

抽出第乙個seed元素,p

然後把p丟到atrr是過濾篩選器中去匹配下,看看是否能找到對應的這個屬性

當然還是繼續從右往左邊匹配過濾了

一次是【name=aaron】 => div => from

matchers[i] => expr.filter.attr =>

p.getattribute(『name=aaron』) => 得到結果

function

elementmatcher( matchers )

}return

true

; } :

matchers[0];

}

如果匹配失敗,自然就退出了  return

false ,就不需要在往前找了 ,然後再次遞迴seed

如果成功,就需要再深入的匹配了

因為是從右到左逐個匹配,所以往前走就會遇到關係選擇器的問題,

那麼jquery把四種關係 > + ~ 空的處理給抽出乙個具體的方法就是addcombinator

1 "form div > p[name=aaron]"
2 seed => p
3 篩選[name=aaron]
4 > => addcombinator方法 找到對應關係對映的父節點elem
5 elem中去匹配div 遞迴elementmatcher方法
6 「空」 =>  addcombinator方法找到祖先父節點elem
7 elem中去找form為止
可見這個查詢是及其複雜繁瑣的
總結:
sizzle對選擇器的大概是思路:

分解所有的選擇器為最小單元,從右往左邊開始挑出乙個瀏覽器的api能快速定位的元素tag,id,class節點,這樣就能確定最終的元素跟這個元素是有關係的

然後把剩餘的選擇器單元開始生成乙個匹配器,主要是用來做篩選,最後根據關係分組

如果就依次匹配往上查詢,通過關係處理器定位上乙個節點的元素,通過普通匹配器去確定是否為可選的內容

sizzle分析記錄 分解流程

js form div p name aaron 解析的流程 編譯器 分5個步驟 涉及 tag元素 關係選擇器 屬性選擇器 1 通過tokenize詞法分析器分組 2 遍歷tokens,從右邊往左邊開始篩選,最快定位到目標元素合集 先看看有沒有搜尋器find,搜尋器就是瀏覽器一些原生的取dom介面,...

sizzle分析記錄 自定義偽類選擇器

可見性 隱藏物件沒有寬高,前提是用display none處理的 jquery.expr.filters.hidden function elem jquery.expr.filters.visible function elem 內容獲取文字內容通過indexof匹配 contains markf...

sizzle分析記錄 自定義偽類選擇器

可見性 隱藏物件沒有寬高,前提是用display none處理的 jquery.expr.filters.hidden function elem jquery.expr.filters.visible function elem 內容獲取文字內容通過indexof匹配 contains markf...