天天看點

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

繼續閱讀