前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jQuery源码研究:选择器

jQuery源码研究:选择器

作者头像
前端_AWhile
发布2019-08-29 15:04:16
5720
发布2019-08-29 15:04:16
举报
文章被收录于专栏:前端一会前端一会

jQuery的css选择器,是一大亮点,其实现源码也可单独拎出来作为模块使用。

先看个整体,在jQuery源码中在行229-2752区域。

代码语言:javascript
复制
var Sizzle = (function(window){
    // 具体实现暂略...
})(window)

css选择器的具体实现是一个匿名自执行函数,传入参数为window对象。函数顶部定义若干变量,包括本地文档变量、特定实例数据和特定实例方法,此外还定义了一些为选择器字符串服务的正则表达式。数量太多就不一一列举了,感兴趣的可以自己去看源码吧。

方法的主体从行715开始直到结束,定义了Sizzle构造函数,若干工具方法和Sizeele静态方法及属性,概览看下图,由于内容太多,只截部分:

1、Sizzle构造函数:

代码语言:javascript
复制
function Sizzle( selector, context, results, seed ){
    var m, i, elem, nid, match, groups, newSelector,
        newContext = context && context.ownerDocument,
        //上下文默认为document,节点类型默认为9
        nodeType = context ? context.nodeType : 9;
    results = results || [];

    // 对选择器值为非字符串、为假、节点类型不符合要求时的返回值进行处理
    if ( typeof selector !== "string" || !selector ||
        nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {

        return results;
    }

    // 操作HTML文档
    if ( !seed ) {

        if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
            setDocument( context );
        }
        context = context || document;

        if ( documentIsHTML ) {

            if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {

                // ID 选择器
                if ( (m = match[1]) ) {

                    // 文档内容
                    if ( nodeType === 9 ) {
                        if ( (elem = context.getElementById( m )) ) {

                            if ( elem.id === m ) {
                                results.push( elem );
                                return results;
                            }
                        } else {
                            return results;
                        }

                    // 元素内容 
                    } else {

                        if ( newContext && (elem = newContext.getElementById( m )) &&
                            contains( context, elem ) &&
                            elem.id === m ) {

                            results.push( elem );
                            return results;
                        }
                    }

                // 类型选择器
                } else if ( match[2] ) {
                    push.apply( results, context.getElementsByTagName( selector ) );
                    return results;

                // Class 选择器
                } else if ( (m = match[3]) && support.getElementsByClassName &&
                    context.getElementsByClassName ) {

                    push.apply( results, context.getElementsByClassName( m ) );
                    return results;
                }
            }

            if ( support.qsa &&
                !compilerCache[ selector + " " ] &&
                (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {

                if ( nodeType !== 1 ) {
                    newContext = context;
                    newSelector = selector;

                } else if ( context.nodeName.toLowerCase() !== "object" ) {

                    if ( (nid = context.getAttribute( "id" )) ) {
                        nid = nid.replace( rcssescape, fcssescape );
                    } else {
                        context.setAttribute( "id", (nid = expando) );
                    }

                    groups = tokenize( selector );
                    i = groups.length;
                    while ( i-- ) {
                        groups[i] = "#" + nid + " " + toSelector( groups[i] );
                    }
                    newSelector = groups.join( "," );

                    newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
                        context;
                }

                if ( newSelector ) {
                    try {
                        push.apply( results,
                            newContext.querySelectorAll( newSelector )
                        );
                        return results;
                    } catch ( qsaError ) {
                    } finally {
                        if ( nid === expando ) {
                            context.removeAttribute( "id" );
                        }
                    }
                }
            }
        }
    }

    // 返回 调用select()方法后的值
    return select( selector.replace( rtrim, "$1" ), context, results, seed );
}

Sizzle函数是整个css选择器的入口函数。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-12-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端小二 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档