介紹
這是一個CSS選擇器引擎,用于解析像div > p + .aaron[type="checkbox"], #id:first-child這樣的CSS選擇器。
為什么會有Sizzle是因為以前的瀏覽器只有getElementById、getElementsByTagName、getElementsByClassName這三種獲取DOM的手段,是沒法使用上面的css選擇器去獲取DOM元素的。但現(xiàn)在的瀏覽器都提供了document.querySelectorAll接口去獲取DOM,所以Sizzle也就沒用了。既然Sizzle都沒用了為什么還要去學(xué)習(xí)它的源碼,因為它很有意思??偟膩碚f,學(xué)習(xí)了Sizzle的源碼之后雖然不能提升工作能力,但是能夠開闊思路。
解析流程
詞法解析
以div > p + .aaron[type="checkbox"], #id:first-child這個選擇器為例來分析解析流程,先是把選擇器分解成一個個單元,單元結(jié)構(gòu)如下
{
value: '匹配到的字符串',
type: '對應(yīng)的Token類型',
matches: '正則匹配到的一個結(jié)構(gòu)'
}
上面的選擇器拆分之后就是
[
[
{ value: "div", type: "TAG", matches: Array },
{ value: " > ", type: ">" },
{ value: "p", type: "TAG", matches: Array },
{ value: " + ", type: "+" },
{ value: ".aaron", type: "CLASS", matches: Array },
{ value: "[type='checkbox']", type: "CLASS", matches: Array }
],
[
{ value: "#id", type: "ID", matches: Array },
{ value: ":first-child", type: "CHILD", matches: Array }
]
]
篩選seed合集
然后是尋找種子合集(seed),從右往左查詢,找到類型為ID、TAG、CLASS中的一種,通過getElementById、getElementsByTagName、getElementsByClassName獲取DOM元素,然后重組選擇器。
以div > p + .aaron[type="checkbox"]為例來說,從右往左查詢到.aaron,然后通過getElementsByClassName將獲取到的DOM元素并保存在seed中。將{ value: ".aaron", type: "CLASS", matches: Array }從tokens序列中刪除,重組選擇器為div > p + [type="checkbox"]。
預(yù)編譯
遍歷tokens序列然后生成一個個的匹配器
// 遍歷Token序列生成匹配器
function matcherFromTokens(tokens) {
var
i,
token,
matcher,
matchers = []
;
for (i = 0; i < tokens.length; i++) {
token = tokens[i];
matcher = Expr.filter[token.type].apply(null, token.matches);
matchers.push(matcher);
}
return elementMatcher(matchers);
}
匹配
將DOM元素挨個傳入匹配器中,返回為true就是我們要找的目標(biāo)元素
var results = [];
var matcher = matcherFromTokens(tokens); // 生成匹配器
if (matcher(elem)) {
results.push(elem)
}
總體流程就是這么回事