matcher就是elementMatcher函數(shù)的包裝,整個(gè)匹配的核心就在這個(gè)里面了:
function( elem, context, xml ) { var i = matchers.length; while ( i-- ) { if ( !matchers[i]( elem, context, xml ) ) { return false; } } return true; }
我們先來回顧下這個(gè)matchers的組合原理,這個(gè)地方是最繞的,也是最暈的,所以還是要深入的理解才行哦。
先上個(gè)簡單的流程圖:
執(zhí)行分解:
第一步:
div > p + div.aaron input[type="checkbox"]
從右邊剝離出原生API能使用的接口屬性
context.getElementsByTagName( input )
所以找到了input,因?yàn)橹豢梢杂胻ag是查詢,但是此時(shí)結(jié)果是個(gè)合集,引入seed的概念,稱之為種子合集。
第二步:
div > p + div.aaron [type="checkbox"]
重組選擇器,踢掉input,得到新的tokens詞法元素哈希表。
第三步:
通過matcherFromTokens函數(shù),然后根據(jù)關(guān)系選擇器 【">","空","~","+"】拆分分組,因?yàn)镈OM中的節(jié)點(diǎn)都是存在關(guān)系的,所以引入Expr.relative -> first:true 兩個(gè)關(guān)系的“緊密”程度,用于組合最佳的篩選。
一次按照如下順序解析并且編譯閉包函數(shù),編譯規(guī)則:div > p + div.aaron [type="checkbox"]。
編譯成4組閉包函數(shù),然后在前后在合并組合成一組:
div > p + div.aaron input[type="checkbox"]
先看構(gòu)造一組編譯函數(shù)
A: 抽出div元素,對應(yīng)的是TAG類型
B: 通過Expr.filter找到對應(yīng)匹配的處理器,返回一個(gè)閉包處理器
如TAG方法:
"TAG": function( nodeNameSelector ) { var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); return nodeNameSelector === "*" ? function() { return true; } : function( elem ) { return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; }; },
C:將返回的curry方法放入到matchers匹配器組中,繼續(xù)分解
D:抽出子元素選擇器 '>' ,對應(yīng)的類型 type: ">"
E:通過Expr.relative找到elementMatcher方法分組合并多個(gè)詞素的的編譯函數(shù)
function(elem, context, xml) { var i = matchers.length; while (i--) { if (!matchers[i](elem, context, xml)) { return false; } }
所以這里其實(shí)就是執(zhí)行了各自Expr.filter匹配中的的判斷方法了,看到這里matcher方法原來運(yùn)行的結(jié)果都是bool值,所以這里只返回了一個(gè)組合閉包,通過這個(gè)篩選閉包,各自處理自己內(nèi)部的元素。
F:返回的這個(gè)匹配器還是不夠的,因?yàn)闆]有規(guī)范搜索范圍的優(yōu)先級,所以這時(shí)候還要引入addCombinator方法
G:根據(jù)Expr.relative -> first:true 兩個(gè)關(guān)系的“緊密”程度
如果是親密關(guān)系addCombinator返回:
function( elem, context, xml ) { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { return matcher( elem, context, xml ); } } }
所以可見如果是緊密關(guān)系的位置詞素,找到第一個(gè)親密的節(jié)點(diǎn),立馬就用終極匹配器判斷這個(gè)節(jié)點(diǎn)是否符合前面的規(guī)則。
請驗(yàn)證,完成請求
由于請求次數(shù)過多,請先驗(yàn)證,完成再次請求
打開微信掃碼自動綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報(bào)