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