天天看点

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

<b>3.1 总体结构</b>

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: { "+", "&gt;", "", "~"

},

// 块表达式查找函数集

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 ) {

           var oldsizzle = sizzle;

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

               // 尝试调用方法

queryselectorall() 查找元素

               // 如果上下文是

document,则直接调用 queryselectorall() 查找元素

               return makearray(

context.queryselectorall(query), extra );

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

               // 查找元素

context.queryselectorall( "[id='" + nid + "'] " +

               query ), extra );

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

oldsizzle()

               return oldsizzle(query, context,

extra, seed);

};

})();

   }

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

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 &gt; 0;

           };

}

检测浏览器是否支持 getelementsbyclassname()

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的方法、功能和调用关系

继续阅读