jQuery源码笔记.jpg

jQuery源码二周目#9 Sizzle

2020-10-24  本文已影响0人  柠檬果然酸

介绍

这是一个CSS选择器引擎,用于解析像div > p + .aaron[type="checkbox"], #id:first-child这样的CSS选择器。

为什么会有Sizzle是因为以前的浏览器只有getElementByIdgetElementsByTagNamegetElementsByClassName这三种获取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中的一种,通过getElementByIdgetElementsByTagNamegetElementsByClassName获取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)
}

总体流程就是这么回事

上一篇下一篇

猜你喜欢

热点阅读