美文网首页jQuery源码笔记.jpg
jQuery源码#3 Sizzle 处理Token序列

jQuery源码#3 Sizzle 处理Token序列

作者: 柠檬果然酸 | 来源:发表于2020-04-15 22:37 被阅读0次

    本节内容
    1.Sizzle.select

    如何处理Token序列
    Sizzle引擎没有直接从HTML获取DOM的手段,它是通过浏览器接口获取DOM对象。浏览器接口有4种:getElementById、getElementsByClassName、getElementsByName、getElementsByTagName,所以Sizzle只能处理ID,CLASS,TAG这3中情况。

    总结下来:将Token序列从后往前查找,找到ID,CLASS,TAG中的一种便通过浏览器接口获取DOM对象,并且将获取到的对象保存在seed种子集合中。

    Sizzle.select
    寻找到种子集合并将它保存在seed中,然后重组选择器

    select = Sizzle.select = function( selector, context, results, seed ) {
        var i, tokens, token, type, find,
            compiled = typeof selector === "function" && selector,
            match = !seed && tokenize( ( selector = compiled.selector || selector ) );
    
        results = results || [];
    
        // 如果只是单个选择器的情况,也即是没有逗号的情况:div, p,可以特殊优化一下
        if ( match.length === 1 ) {
            tokens = match[ 0 ] = match[ 0 ].slice( 0 );
    
            // 如果第一个是selector是id我们可以设置context快速查找
            if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
                context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {
    
                context = ( Expr.find[ "ID" ]( token.matches[ 0 ]
                    .replace( runescape, funescape ), context ) || [] )[ 0 ];
                if ( !context ) { // 如果context这个元素(selector第一个id选择器)都不存在就不用查找了
                    return results;
                } else if ( compiled ) {
                    context = context.parentNode;
                }
    
                // 去掉第一个id选择器
                selector = selector.slice( tokens.shift().value.length );
            }
    
            // 即是表示如果没有一些结构伪类,这些是需要用另一种方式过滤,在之后文章再详细剖析
            // 那么就从最后一条规则开始,先找出seed集合
            i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length;
    
            while ( i-- ) {
                token = tokens[ i ];
    
                // 如果遇到了关系选择器中止
                // > + ~ 空格
                if ( Expr.relative[ ( type = token.type ) ] ) {
                    break;
                }
    
                // 是否为ID,CLASS,TAG中的一种
                if ( ( find = Expr.find[ type ] ) ) {
    
                    // 搜索到符合条件的初始集合seed
                    // find可以看成getElementsByTagName
                    if ( ( seed = find(
                        token.matches[ 0 ].replace( runescape, funescape ),
                        rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) ||
                            context
                    ) ) ) {
                        tokens.splice( i, 1 );
                        selector = seed.length && toSelector( tokens );
    
                        // 如果当前剩余的选择器为空,提前返回结果
                        if ( !selector ) {
                            push.apply( results, seed );
                            return results;
                        }
    
                        // 已经找到了符合条件的seed集合,不管前边是否还有其他Token,跳出去
                        break;
                    }
                }
            }
        }
    
        // 暂时不知道有什么用,应该是进一步过滤seed集合的
        ( compiled || compile( selector, match ) )(
            seed,
            context,
            !documentIsHTML,
            results,
            !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
        );
        return results;
    };
    

    相关文章

      网友评论

        本文标题:jQuery源码#3 Sizzle 处理Token序列

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