jQuery技术内幕:深入解析jQuery架构设计与实现原理.3.1 总体结构

    xiaoxiao2024-01-14  157

    3.1 总体结构

    Sizzle的总体源码结构如代码清单3-1所示,为了方便解释,代码中增加了注释:

    代码清单3-1  Sizzle 的总体源码结构

    (function(){

       // 选择器引擎入口,查找与选择器表达式 selector 匹配的元素集合

       var Sizzle = function( selector, context, results, seed )  { ... };

       // 工具方法,排序、去重

       Sizzle.uniqueSort = function( results )  { ... };

       // 便捷方法,使用指定的选择器表达式 expr 对元素集合 set 进行过滤

       Sizzle.matches = function( expr, set )  { ... };

       // 便捷方法,检查某个元素 node 是否匹配选择器表达式 expr

       Sizzle.matchesSelector = function( node, expr )  { ... };

       // 内部方法,对块表达式进行查找

       Sizzle.find = function( expr, context, isXML )  { ... };

       // 内部方法,用块表达式过滤元素集合

       Sizzle.filter = function( expr, set, inplace, not )  { ... };

       // 工具方法,抛出异常

       Sizzle.error = function( msg )  { ... };

       // 工具方法,获取 DOM 元素集合的文本内容

       var getText = Sizzle.getText = function( elem )  { ... };

       // 扩展方法和属性

       var Expr = Sizzle.selectors = {

           // 块表达式查找顺序

           order: [ "ID", "NAME", "TAG" ],

           // 正则表达式集,用于匹配和解析块表达式

           match:  { ID, CLASS, NAME, ATTR, TAG, CHILD, POS, PSEUDO },

           leftMatch:  { ... },

           // 属性名修正函数集

           attrMap: { "class", "for" },

           // 属性值读取函数集

           attrHandle:  { href, type },

           // 块间关系过滤函数集

           relative: { "+", ">", "", "~" },

           // 块表达式查找函数集

           find: { ID, NAME, TAG },

           // 块表达式预过滤函数集

           preFilter: { CLASS, ID, TAG, CHILD, ATTR, PSEUDO, POS },

           // 伪类过滤函数集

           filters: { enabled, disabled, checked, selected, parent, empty, has, header,

           text, radio, checkbox, file, password, submit, image, reset, button, input,

           focus },

           // 位置伪类过滤函数集

           setFilters: { first, last, even, odd, lt, gt, nth, eq },

           // 块表达式过滤函数集

           filter: { PSEUDO, CHILD, ID, TAG, CLASS, ATTR, POS }

       };

     

       // 如果支持方法 querySelectorAll(),则调用该方法查找元素

       if ( document.querySelectorAll ) {

           (function(){

               var oldSizzle = Sizzle;

               Sizzle = function( query, context, extra, seed ) {

                   // 尝试调用方法 querySelectorAll() 查找元素

                   // 如果上下文是 document,则直接调用 querySelectorAll() 查找元素

                   return makeArray( context.querySelectorAll(query), extra );

                   // 如果上下文是元素,则为选择器表达式增加上下文,然后调用 querySelectorAll()

                   // 查找元素

                   return makeArray( context.querySelectorAll( "[id='" + nid + "'] " +

                   query ), extra );

                   // 如果查找失败,则仍然调用 oldSizzle()

                   return oldSizzle(query, context, extra, seed);

               };

           })();

       }

     

       // 如果支持方法 matchesSelector(),则调用该方法检查元素是否匹配选择器表达式

       (function(){

           var matches = html.matchesSelector

                            || html.mozMatchesSelector

                            || html.webkitMatchesSelector

                            || html.msMatchesSelector;

           // 如果支持方法 matchesSelector()

           if ( matches ) {

               Sizzle.matchesSelector = function( node, expr ) {

                   // 尝试调用方法 matchesSelector()

                   var ret = matches.call( node, expr );

                   return ret;

                   // 如果查找失败,则仍然调用 Sizzle()

                   return Sizzle(expr, null, null, [node]).length > 0;

               };

           }

       })();

     

       // 检测浏览器是否支持 getElementsByClassName()

       (function(){

           Expr.order.splice(1, 0, "CLASS");

           Expr.find.CLASS = function( match, context, isXML )  { ... };

       })();

       // 工具方法,检测元素 a 是否包含元素 b

       Sizzle.contains = function( a, b ) { ... };

    })();

    代码清单3-1中的变量Expr与Sizzle.selectors指向了同一个对象,这么做是为了减少拼写字符数、缩短作用域链,并且方便压缩。但是为了直观和避免混淆,本章在描述中统一使用Sizzle.selectors。

    代码清单3-1中已经介绍了浏览器支持方法querySelectorAll()时的查找过程,本章后面的内容将介绍和分析在不支持的情况下,Sizzle是如何模拟方法querySelectorAll()的行为的。另外,为了简化描述,在后文中把“块表达式查找函数集”“块表达式预过滤函数集”“块表达式过滤函数集”分别简称为“查找函数集”“预过滤函数集”“过滤函数集”。

    代码清单3-1中的方法和属性大致可以分为4类:公开方法、内部方法、工具方法、扩展方法及属性。它们之间的调用关系如图3-1所示。

     

    图3-1 Sizzle的方法、功能和调用关系

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)