您當前位置:圖趣網(wǎng)(Tuquu) >> 網(wǎng)頁設計教程 >> 移動前端 >> 瀏覽設計教程

jQuery選擇器探討進階

 

jQuery選擇器探討

在jQuery中,當用戶把選擇器表達式作為參數(shù)傳遞給$()函數(shù)時,jQery的Sizzle先對這個選擇器表達式進行語法分析,然后再決定如何獲得表達式所代表的這些元素。在框架底層,Sizzle應用了瀏覽器所支持的最高效的DOM 方法來獲取一個節(jié)點列表(nodeList),這個節(jié)點列表是一個類似于數(shù)組的對象的DOM元素的集合。下面的列表展示了jQuery的Sizzle內部采用的瀏覽器DOM遍歷方法和瀏覽器的支持情況:

  1. 1. .getElementById()  瀏覽器支持情況:IE 6+, Firefox 3+, Safari 3+, Chrome 4+, and Opera 10+;
  2. 2. .getElementsByTagName()  瀏覽器支持情況:IE 6+, Firefox 3+, Safari 3+,Chrome 4+, and Opera 10+;
  3. 3. .getElementsByClassName() 瀏覽器支持情況:IE 9+, Firefox 3+, Safari4+, Chrome 4+, and Opera 10+;
  4. 4. .querySelectorAll() (這個是瀏覽器內置的css選擇符查詢元素方法,比getElementsByTagName和getElementsByClassName效率要高很多。)瀏覽器支持情況:IE 8+, Firefox 3.5+, Safari 3+, Chrome 4+, and Opera 10+;

 

如果是最新版本的瀏覽器,ie8以上,Sizzle采用.querySelectorAll()方法來獲取對應的DOM元素集,這個方法以CSS表達式為string參數(shù),獲取DOM元素的速度比其他3個方法更快更高效。當jQuery 選擇器表達式中包含自定義選擇符,比如eq() 或  :odd 或 :even,因為沒有配對的CSS表達式,jQuery只能采用前3個方法(.getElementById(),.getElementsByTagName(),.getElementsByClassName() )來逐個遍歷總元素集(通過 document.getElementsByTagName(‘*’)獲得),再檢驗元素,最終獲得對應于選擇表達式的元素集,這種遍歷查找性能消耗比較大。因此,如果不能用.querySelectorAll()直接獲得對應的元素,采用另外3種方法獲得元素集的效率要差一些,所以,在jqury中,一些選擇器表達式普遍快于另外一些選擇器表達式,把選擇器中的偽類移到相應的方法中可以加速查找頁面文檔dom元素的時間。為了簡單起見,我們把jQuery中用.getElementById (),.getElementsByTagName(),.getElementsByClassName() 這3個方法的結合來查找元素稱為:循環(huán)和檢驗(loop and test)過程。

下面我們來看幾個例子:

我們采用$(‘input[type="text"]‘)和$(‘input:text’)這兩個表達式來檢驗上述論點。$(‘input[type="text"]‘),因為采用了CSS的屬性表達式,所以Sizzle用.querySelectorAll()來查找元素,$(‘input:text’),采用了jQuery自定義的選擇器表達式:text,.querySelectorAll()方法無法解析,所以Sizzle底層采用循環(huán)和檢驗(loop and test)過程。

結果如下圖所示:

縱軸中的數(shù)字代表在規(guī)定時間內,表達式選擇器方法可以被執(zhí)行的次數(shù),因此,數(shù)值越高,執(zhí)行效率越好,代表執(zhí)行時間越短,性能越好。在現(xiàn)代瀏覽器中,(Chrome 12, Firefox4, and Safari 5,IE 8+) ,CSS選擇器表達式底層采用.querySelectorAll()方法,很好的實現(xiàn)了優(yōu)勢,平均而言,大概是自定義選擇器表達式性能表現(xiàn)的2倍。但是,在ie7中,這兩個選擇器的性能表現(xiàn)差不多,這是因為在ie7環(huán)境下,Sizzle都采用了循環(huán)和檢驗(loop and test)過程累找到相應的元素,(因為ie7不支持.querySelectorAll()方法。),所以在編寫jQuery的選擇器函數(shù)進行事件注冊時,要特別注意,可能你的代碼在ie8以上執(zhí)行正確,但在ie7中,$()函數(shù)返回的object.length將是0。比如下面這個列子的代碼,在ie7下會導致執(zhí)行錯誤:

$(document).ready(function() {
  var trigger = $('#filter_sample');
  var url = $('+ a',trigger).attr('href');
});

在ie6,ie7中,變量url的值將是undefined,因為ie7不支持.querySelectorAll()方法,而按.getElementsByTagName()方法解析上面的選擇表達式得到的結果集為空,所以$(‘+ a’,trigger)在ie7下將得到一個空數(shù)組對象。自然對這個空數(shù)組取href屬性,返回undefined了。所以,在jQuery中,合理的編寫選擇表達式是十分重要的。

在瀏覽器中,$(‘input:eq(1)’)和$(‘input’).eq(1)的性能表現(xiàn)差異比較大:

從上圖可知,甚至在ie7中,把:eq()選擇器移出表達式,轉而采用.eq()方法,性能也有100%的提升。為何如此?當jQuery遇到單個id,標簽名,類名,選擇器就會以坐快車的形式快速調用瀏覽器支持的DOM方法,在上面的例子中,使用簡單的input標簽作為$() 函數(shù)的參數(shù),將會導致一個非常快速的查詢。然后.eq(1)方法簡單的調用數(shù)組函數(shù)來取回該元素集的第2個元素。

總的來說,做為一個常見的規(guī)則,我們應該盡量使用符合CSS語法規(guī)范的CSS選擇器表達式,以此來避免使用jQuery自定義的選擇器表達式,在jQuery選擇器性能測試方面,可以采用http://jsperf.com/這個在線工具來檢驗哪種編寫方法對性能的改進影響更大。

另外2個跟jQuery選擇器有關的性能問題是盡量采用鏈式調用來操作緩存選擇器結果集。因為每一個$()的調用都會導致一次新的查找,所以,采用鏈式調用和設置變量緩存結果集,減少查找,提升性能。

鏈式調用示例:

$(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();
});

通過鏈式調用,采用find(),end(),children(),has,filter()等方法,來過濾結果集,減少$()查找方法調用,提升性能。

緩存結果集示例:

$(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();
});

通過聲明$news變量緩存$(‘#news’)結果集,從而提升后面結果集對象調用方法的性能。

[教程作者:admin]
免責聲明:本站文章系圖趣網(wǎng)整理發(fā)布,如需轉載,請注明出處,素材資料僅供個人學習與參考,請勿用于商業(yè)用途!
本文地址:http://irelandcustomcontracting.com/tutorial/wd1365.html
網(wǎng)頁前端開發(fā)jQuery事件編寫進階
網(wǎng)頁前端開發(fā)IE BUG系列之雙邊距BUG
圖趣網(wǎng)微信
建議反饋
×