美文网首页jQuery源码笔记.jpg
jQuery源码二周目#9 Sizzle

jQuery源码二周目#9 Sizzle

作者: 柠檬果然酸 | 来源:发表于2020-10-24 11:25 被阅读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)
    }
    

    总体流程就是这么回事

    相关文章

      网友评论

        本文标题:jQuery源码二周目#9 Sizzle

        本文链接:https://www.haomeiwen.com/subject/hdvrmktx.html