介绍
这是一个CSS选择器引擎,用于解析像div > p + .aaron[type="checkbox"], #id:first-child
这样的CSS选择器。
为什么会有Sizzle是因为以前的浏览器只有getElementById
、getElementsByTagName
、getElementsByClassName
这三种获取DOM的手段,是没法使用上面的css选择器去获取DOM元素的。但现在的浏览器都提供了document.querySelectorAll
接口去获取DOM,所以Sizzle也就没用了。既然Sizzle都没用了为什么还要去学习它的源码,因为它很有意思。总的来说,学习了Sizzle的源码之后虽然不能提升工作能力,但是能够开阔思路。
解析流程
词法解析
以div > p + .aaron[type="checkbox"], #id:first-child
这个选择器为例来分析解析流程,先是把选择器分解成一个个单元,单元结构如下
{
value: '匹配到的字符串',
type: '对应的Token类型',
matches: '正则匹配到的一个结构'
}
上面的选择器拆分之后就是
[
[
{ 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"]
。
预编译
遍历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就是我们要找的目标元素
var results = [];
var matcher = matcherFromTokens(tokens); // 生成匹配器
if (matcher(elem)) {
results.push(elem)
}
总体流程就是这么回事