jQuery選擇器探討進(jìn)階
jQuery選擇器探討
在jQuery中,當(dāng)用戶把選擇器表達(dá)式作為參數(shù)傳遞給$()函數(shù)時(shí),jQery的Sizzle先對(duì)這個(gè)選擇器表達(dá)式進(jìn)行語(yǔ)法分析,然后再?zèng)Q定如何獲得表達(dá)式所代表的這些元素。在框架底層,Sizzle應(yīng)用了瀏覽器所支持的最高效的DOM 方法來(lái)獲取一個(gè)節(jié)點(diǎn)列表(nodeList),這個(gè)節(jié)點(diǎn)列表是一個(gè)類似于數(shù)組的對(duì)象的DOM元素的集合。下面的列表展示了jQuery的Sizzle內(nèi)部采用的瀏覽器DOM遍歷方法和瀏覽器的支持情況:
- 1. .getElementById() 瀏覽器支持情況:IE 6+, Firefox 3+, Safari 3+, Chrome 4+, and Opera 10+;
- 2. .getElementsByTagName() 瀏覽器支持情況:IE 6+, Firefox 3+, Safari 3+,Chrome 4+, and Opera 10+;
- 3. .getElementsByClassName() 瀏覽器支持情況:IE 9+, Firefox 3+, Safari4+, Chrome 4+, and Opera 10+;
- 4. .querySelectorAll() (這個(gè)是瀏覽器內(nèi)置的css選擇符查詢?cè)胤椒?,比getElementsByTagName和getElementsByClassName效率要高很多。)瀏覽器支持情況:IE 8+, Firefox 3.5+, Safari 3+, Chrome 4+, and Opera 10+;
如果是最新版本的瀏覽器,ie8以上,Sizzle采用.querySelectorAll()方法來(lái)獲取對(duì)應(yīng)的DOM元素集,這個(gè)方法以CSS表達(dá)式為string參數(shù),獲取DOM元素的速度比其他3個(gè)方法更快更高效。當(dāng)jQuery 選擇器表達(dá)式中包含自定義選擇符,比如eq() 或 :odd 或 :even,因?yàn)闆](méi)有配對(duì)的CSS表達(dá)式,jQuery只能采用前3個(gè)方法(.getElementById(),.getElementsByTagName(),.getElementsByClassName() )來(lái)逐個(gè)遍歷總元素集(通過(guò) document.getElementsByTagName(‘*’)獲得),再檢驗(yàn)元素,最終獲得對(duì)應(yīng)于選擇表達(dá)式的元素集,這種遍歷查找性能消耗比較大。因此,如果不能用.querySelectorAll()直接獲得對(duì)應(yīng)的元素,采用另外3種方法獲得元素集的效率要差一些,所以,在jqury中,一些選擇器表達(dá)式普遍快于另外一些選擇器表達(dá)式,把選擇器中的偽類移到相應(yīng)的方法中可以加速查找頁(yè)面文檔dom元素的時(shí)間。為了簡(jiǎn)單起見,我們把jQuery中用.getElementById (),.getElementsByTagName(),.getElementsByClassName() 這3個(gè)方法的結(jié)合來(lái)查找元素稱為:循環(huán)和檢驗(yàn)(loop and test)過(guò)程。
下面我們來(lái)看幾個(gè)例子:
我們采用$(‘input[type="text"]‘)和$(‘input:text’)這兩個(gè)表達(dá)式來(lái)檢驗(yàn)上述論點(diǎn)。$(‘input[type="text"]‘),因?yàn)椴捎昧薈SS的屬性表達(dá)式,所以Sizzle用.querySelectorAll()來(lái)查找元素,$(‘input:text’),采用了jQuery自定義的選擇器表達(dá)式:text,.querySelectorAll()方法無(wú)法解析,所以Sizzle底層采用循環(huán)和檢驗(yàn)(loop and test)過(guò)程。
結(jié)果如下圖所示:
縱軸中的數(shù)字代表在規(guī)定時(shí)間內(nèi),表達(dá)式選擇器方法可以被執(zhí)行的次數(shù),因此,數(shù)值越高,執(zhí)行效率越好,代表執(zhí)行時(shí)間越短,性能越好。在現(xiàn)代瀏覽器中,(Chrome 12, Firefox4, and Safari 5,IE 8+) ,CSS選擇器表達(dá)式底層采用.querySelectorAll()方法,很好的實(shí)現(xiàn)了優(yōu)勢(shì),平均而言,大概是自定義選擇器表達(dá)式性能表現(xiàn)的2倍。但是,在ie7中,這兩個(gè)選擇器的性能表現(xiàn)差不多,這是因?yàn)樵趇e7環(huán)境下,Sizzle都采用了循環(huán)和檢驗(yàn)(loop and test)過(guò)程累找到相應(yīng)的元素,(因?yàn)閕e7不支持.querySelectorAll()方法。),所以在編寫jQuery的選擇器函數(shù)進(jìn)行事件注冊(cè)時(shí),要特別注意,可能你的代碼在ie8以上執(zhí)行正確,但在ie7中,$()函數(shù)返回的object.length將是0。比如下面這個(gè)列子的代碼,在ie7下會(huì)導(dǎo)致執(zhí)行錯(cuò)誤:
$(document).ready(function() { var trigger = $('#filter_sample'); var url = $('+ a',trigger).attr('href'); });
在ie6,ie7中,變量url的值將是undefined,因?yàn)閕e7不支持.querySelectorAll()方法,而按.getElementsByTagName()方法解析上面的選擇表達(dá)式得到的結(jié)果集為空,所以$(‘+ a’,trigger)在ie7下將得到一個(gè)空數(shù)組對(duì)象。自然對(duì)這個(gè)空數(shù)組取href屬性,返回undefined了。所以,在jQuery中,合理的編寫選擇表達(dá)式是十分重要的。
在瀏覽器中,$(‘input:eq(1)’)和$(‘input’).eq(1)的性能表現(xiàn)差異比較大:
從上圖可知,甚至在ie7中,把:eq()選擇器移出表達(dá)式,轉(zhuǎn)而采用.eq()方法,性能也有100%的提升。為何如此?當(dāng)jQuery遇到單個(gè)id,標(biāo)簽名,類名,選擇器就會(huì)以坐快車的形式快速調(diào)用瀏覽器支持的DOM方法,在上面的例子中,使用簡(jiǎn)單的input標(biāo)簽作為$() 函數(shù)的參數(shù),將會(huì)導(dǎo)致一個(gè)非常快速的查詢。然后.eq(1)方法簡(jiǎn)單的調(diào)用數(shù)組函數(shù)來(lái)取回該元素集的第2個(gè)元素。
總的來(lái)說(shuō),做為一個(gè)常見的規(guī)則,我們應(yīng)該盡量使用符合CSS語(yǔ)法規(guī)范的CSS選擇器表達(dá)式,以此來(lái)避免使用jQuery自定義的選擇器表達(dá)式,在jQuery選擇器性能測(cè)試方面,可以采用http://jsperf.com/這個(gè)在線工具來(lái)檢驗(yàn)?zāi)姆N編寫方法對(duì)性能的改進(jìn)影響更大。
另外2個(gè)跟jQuery選擇器有關(guān)的性能問(wèn)題是盡量采用鏈?zhǔn)秸{(diào)用來(lái)操作和緩存選擇器結(jié)果集。因?yàn)槊恳粋€(gè)$()的調(diào)用都會(huì)導(dǎo)致一次新的查找,所以,采用鏈?zhǔn)秸{(diào)用和設(shè)置變量緩存結(jié)果集,減少查找,提升性能。
鏈?zhǔn)秸{(diào)用示例:
$(document).ready(function() { function stripe() { $('#news').find('tr.alt').removeClass('alt').end().find('tbody').each(function() { $(this).children(':visible').has('td').filter(':group(3)').addClass('alt'); }); } stripe(); });
通過(guò)鏈?zhǔn)秸{(diào)用,采用find(),end(),children(),has,filter()等方法,來(lái)過(guò)濾結(jié)果集,減少$()查找方法調(diào)用,提升性能。
緩存結(jié)果集示例:
$(document).ready(function() { var $news = $('#news'); function stripe() { $news.find('tr.alt').removeClass('alt'); $news.find('tbody').each(function() { $(this).children(':visible').has('td').filter(':group(3)').addClass('alt'); }); } stripe(); });
通過(guò)聲明$news變量緩存$(‘#news’)結(jié)果集,從而提升后面結(jié)果集對(duì)象調(diào)用方法的性能。
本文地址:http://m.likemindfilms.com/tutorial/wd1365.html
- 專訪:石墨文檔產(chǎn)品總監(jiān)羅穎
- UI設(shè)計(jì)不得不知的移動(dòng)端UI尺寸適
- 光音移動(dòng)設(shè)計(jì)規(guī)范 — 表單類
- 體驗(yàn)設(shè)計(jì)中的排序問(wèn)題
- 網(wǎng)頁(yè)設(shè)計(jì)精粹 網(wǎng)頁(yè)中那些迷人的按
- aliued:響應(yīng)式設(shè)計(jì)的現(xiàn)狀與趨勢(shì)
- 10個(gè)智能對(duì)象處理的ps技巧
- 網(wǎng)頁(yè)UI - 原子設(shè)計(jì)理論(上)
- 如何通過(guò)設(shè)計(jì)提升banner點(diǎn)擊率?
- 晉小彥視覺(jué)設(shè)計(jì)系列文章(二):全屏