传智播客旗下技术交流社区北京校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 不二晨 黑马程序员官方团队   /  2019-1-13 12:44  /  49 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

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

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

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

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

1、Sizzle构造函数:

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 = "#" + nid + " " + toSelector( groups );
                                        }
                                        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 );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
Sizzle函数是整个css选择器的入口函数。
---------------------
【转载,仅作分享,侵删】
作者: 一期一会
原文:https://blog.csdn.net/qq_34832846/article/details/86298051


分享至 : QQ空间
收藏

1 个回复

倒序浏览
奈斯
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马