<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: { "+", ">", "", "~"
},
// 块表达式查找函数集
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 > 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的方法、功能和调用关系