jquery的show/hide性能測試

這篇文章是jQuery各類show/hide方式的性能測試。做者之因此測試這個源於Robert Duffy在SanFrancisco舉行的jQuery大會上的一句話:「.hide()和.show()的執行速度會比直接改變css慢」。但因爲未能找RobertDuffy問明緣由,因此做者就本身去作了這個測試。下面的翻譯並非全文翻譯,只節選了一些重點。
javascript


用做測試的是一個含有100個div的HTML頁面,div帶有class和一些內容。爲了排除掉尋找這些div所花費的時間,因此把選擇器$('div')緩存起來了。用做測試的jQuery版本是1.4.2,因此測試結果也只是針對這個版本,在其餘版本可能就不是這些結果了。
測試的jQuery方法分別是:css

  • .toggle()
  • .show() 和 .hide()
  • .css({'display':'none'}) 和 .css({'display':'block'})
  • .addClass('hide') 和 .removeClass('hide')
  • 改變<style>元素的一個屬性




在全部瀏覽器中,這兩個方法在隱藏DOM元素上相對來講比較慢。主要緣由在於.hide()方法必須先保存元素的"display"屬性,這樣.show()才能把元素恢復到原來的狀態。這裏用到了.data()這個jQuery方法,把信息保存在DOM元素上。爲了達到這個目的,.hide()在每一個元素上循環了兩次,一次用來保存當前的"display"值,一次用來更新樣式"display"爲"none"。根據源代碼上的註釋,這樣作是爲了防止瀏覽器在每一個循環上進行從新渲染(reflow)。.hide()方法還會檢查你是否傳遞了使用動畫效果的參數,就算傳入一個"0"也會讓性能大打折扣。在第一次調用.hide()的時候性能最慢,在以後再調用則會變快。
在全部瀏覽器中,這兩個方法在隱藏DOM元素上相對來講比較慢。主要緣由在於.hide()方法必須先保存元素的"display"屬性,這樣.show()才能把元素恢復到原來的狀態。這裏用到了.data()這個jQuery方法,把信息保存在DOM元素上。爲了達到這個目的,.hide()在每一個元素上循環了兩次,一次用來保存當前的"display"值,一次用來更新樣式"display"爲"none"。根據源代碼上的註釋,這樣作是爲了防止瀏覽器在每一個循環上進行從新渲染(reflow)。.hide()方法還會檢查你是否傳遞了使用動畫效果的參數,就算傳入一個"0"也會讓性能大打折扣。在第一次調用.hide()的時候性能最慢,在以後再調用則會變快。
在全部瀏覽器中,這兩個方法在隱藏DOM元素上相對來講比較慢。主要緣由在於.hide()方法必須先保存元素的"display"屬性,這樣.show()才能把元素恢復到原來的狀態。這裏用到了.data()這個jQuery方法,把信息保存在DOM元素上。爲了達到這個目的,.hide()在每一個元素上循環了兩次,一次用來保存當前的"display"值,一次用來更新樣式"display"爲"none"。根據源代碼上的註釋,這樣作是爲了防止瀏覽器在每一個循環上進行從新渲染(reflow)。.hide()方法還會檢查你是否傳遞了使用動畫效果的參數,就算傳入一個"0"也會讓性能大打折扣。在第一次調用.hide()的時候性能最慢,在以後再調用則會變快。
Browser hide/show
FireFox 3.6 29ms / 10ms
Safari 4.05 6ms / 1ms
Opera 10.10 9ms / 1ms
Chrome 5.0.3 5ms / 1ms
IE 6.0 31ms / 16ms
IE 7.0 15ms / 16ms




這個方法是最慢的。它會檢查選擇器返回的每個元素當前是否可見,若是可見的話就調用.hide()方法,不可見則調用.show()方法。不但如此,它不只會檢查你是否傳遞了一個boolean值進去阻止.hide()或者.show()的執行,還會檢查看你是否傳入了function來進行切換(toggle)而不是對可見性進行切換。看起來這個方法還有很大的改善空間,例如能夠先一次過把隱藏的元素select出來,而後調用.show()方法,同時把其他的元素select出來調用.hide()方法。
這個方法是最慢的。它會檢查選擇器返回的每個元素當前是否可見,若是可見的話就調用.hide()方法,不可見則調用.show()方法。不但如此,它不只會檢查你是否傳遞了一個boolean值進去阻止.hide()或者.show()的執行,還會檢查看你是否傳入了function來進行切換(toggle)而不是對可見性進行切換。看起來這個方法還有很大的改善空間,例如能夠先一次過把隱藏的元素select出來,而後調用.show()方法,同時把其他的元素select出來調用.hide()方法。
這個方法是最慢的。它會檢查選擇器返回的每個元素當前是否可見,若是可見的話就調用.hide()方法,不可見則調用.show()方法。不但如此,它不只會檢查你是否傳遞了一個boolean值進去阻止.hide()或者.show()的執行,還會檢查看你是否傳入了function來進行切換(toggle)而不是對可見性進行切換。看起來這個方法還有很大的改善空間,例如能夠先一次過把隱藏的元素select出來,而後調用.show()方法,同時把其他的元素select出來調用.hide()方法。
Browser hide/show
FireFox 3.6 80ms / 59ms
Safari 4.05 24ms / 30ms
Opera 10.10 67ms / 201ms
Chrome 5.0.3 55ms / 20ms
IE 6.0 296ms / 78ms
IE 7.0 328ms / 47ms




這是兩個很漂亮的隱藏/顯示DOM元素方法。在Firefox上它的速度是.show()和.hide()的兩倍,而在Safari上則是三倍。不過在IE6,IE7,Chrome和Opera上,兩種方法幾乎沒什麼差異。值得一提的是,對於100個DOM節點來講,兩種方法在Firefox上相差18ms,在Safari相差4ms,速度的差別只會體如今大量節點選擇的時候。不過增長和移除class須要你花費更多的工做,由於你須要建立一個用於隱藏的class,而後還要時刻關注着這個class的優先級以保證DOM能隱藏。jQuery增長和移除class是經過字符串操做的,因此我以爲隨着元素上class數量的增長,這個方法會變慢,可是我還沒對此進行測試過。
這是兩個很漂亮的隱藏/顯示DOM元素方法。在Firefox上它的速度是.show()和.hide()的兩倍,而在Safari上則是三倍。不過在IE6,IE7,Chrome和Opera上,兩種方法幾乎沒什麼差異。值得一提的是,對於100個DOM節點來講,兩種方法在Firefox上相差18ms,在Safari相差4ms,速度的差別只會體如今大量節點選擇的時候。不過增長和移除class須要你花費更多的工做,由於你須要建立一個用於隱藏的class,而後還要時刻關注着這個class的優先級以保證DOM能隱藏。jQuery增長和移除class是經過字符串操做的,因此我以爲隨着元素上class數量的增長,這個方法會變慢,可是我還沒對此進行測試過。
這是兩個很漂亮的隱藏/顯示DOM元素方法。在Firefox上它的速度是.show()和.hide()的兩倍,而在Safari上則是三倍。不過在IE6,IE7,Chrome和Opera上,兩種方法幾乎沒什麼差異。值得一提的是,對於100個DOM節點來講,兩種方法在Firefox上相差18ms,在Safari相差4ms,速度的差別只會體如今大量節點選擇的時候。不過增長和移除class須要你花費更多的工做,由於你須要建立一個用於隱藏的class,而後還要時刻關注着這個class的優先級以保證DOM能隱藏。jQuery增長和移除class是經過字符串操做的,因此我以爲隨着元素上class數量的增長,這個方法會變慢,可是我還沒對此進行測試過。
Browser hide/show
FireFox 3.6 11ms / 11ms
Safari 4.05 2ms / 2ms
Opera 10.10 6ms / 3ms
Chrome 5.0.3 3ms / 1ms
IE 6.0 47ms / 32ms
IE 7.0 15ms / 16ms




這兩個方法也很漂亮。相對於.addClass()和.removeClass(),IE6/7和Opera上的速度都獲得了提高,而在其餘瀏覽器上則能保持水準。當你知道要改變的元素的當前display樣式,或者沒有經過inline的方式去改變元素的display樣式時,這兩個方法很好用。若是你經過inline的方式改變了display樣式,那麼你須要確保在使得元素從新可見時display值要設置正確。若是你只是使用了元素的默認display值或者在css裏設置display值,那麼你只須要用相似.css({'display':''})的方法移除樣式,元素就會恢復到它在css上的樣式或者默認display值。做爲一個類庫,jQuery不能假定元素的display不是經過inline方式設置的,因此它須要被人手的去肯定。不過既然你知道你不會去inline的設置display,那麼你就能夠去避免這個形成緩慢的主要因素。
這兩個方法也很漂亮。相對於.addClass()和.removeClass(),IE6/7和Opera上的速度都獲得了提高,而在其餘瀏覽器上則能保持水準。當你知道要改變的元素的當前display樣式,或者沒有經過inline的方式去改變元素的display樣式時,這兩個方法很好用。若是你經過inline的方式改變了display樣式,那麼你須要確保在使得元素從新可見時display值要設置正確。若是你只是使用了元素的默認display值或者在css裏設置display值,那麼你只須要用相似.css({'display':''})的方法移除樣式,元素就會恢復到它在css上的樣式或者默認display值。做爲一個類庫,jQuery不能假定元素的display不是經過inline方式設置的,因此它須要被人手的去肯定。不過既然你知道你不會去inline的設置display,那麼你就能夠去避免這個形成緩慢的主要因素。
這兩個方法也很漂亮。相對於.addClass()和.removeClass(),IE6/7和Opera上的速度都獲得了提高,而在其餘瀏覽器上則能保持水準。當你知道要改變的元素的當前display樣式,或者沒有經過inline的方式去改變元素的display樣式時,這兩個方法很好用。若是你經過inline的方式改變了display樣式,那麼你須要確保在使得元素從新可見時display值要設置正確。若是你只是使用了元素的默認display值或者在css裏設置display值,那麼你只須要用相似.css({'display':''})的方法移除樣式,元素就會恢復到它在css上的樣式或者默認display值。做爲一個類庫,jQuery不能假定元素的display不是經過inline方式設置的,因此它須要被人手的去肯定。不過既然你知道你不會去inline的設置display,那麼你就能夠去避免這個形成緩慢的主要因素。
Browser hide/show
FireFox 3.6 14ms / 12ms
Safari 4.05 2ms / 1ms
Opera 10.10 2ms / 2ms
Chrome 5.0.3 2ms / 1ms
IE 6.0 16ms / 16ms
IE 7.0 0ms / 0ms // 少於15ms會變成0ms




純粹爲了好玩,我想:若是咱們不在每一個dom節點上花功夫,而是去搗鼓樣式表會怎樣呢?這樣會提升速度嗎?其實就平常使用來講,上面的測試用到的方法已經足夠快了,可是若是頁面上有10000個節點須要進行隱藏和顯示呢?只是把它們所有選擇出來就已經夠慢了。若是我能夠控制樣式表,那麼就能夠徹底避免這些時間花費了。不過我得告訴你,這個方法是有很大風險的。
風險在於控制樣式表時的跨瀏覽器問題。首先,我嘗試能不能經過jQuery插入一個帶有class的"style"標籤,可是卻出現了跨瀏覽器問題。而後我嘗試用javascript去建立stylesheet節點和class,可是實在有太多的API了,要搞清楚須要花很多的時間。最後,放棄了編程的方式,我在head區裏寫了一個帶有class的style標籤。經過編程的方式來建立stylesheet實在是太慢了,可是若是它一旦被建立好,那麼給它一個ID和使用它的"disabled"屬性就是垂手可得的事情了。
純粹爲了好玩,我想:若是咱們不在每一個dom節點上花功夫,而是去搗鼓樣式表會怎樣呢?這樣會提升速度嗎?其實就平常使用來講,上面的測試用到的方法已經足夠快了,可是若是頁面上有10000個節點須要進行隱藏和顯示呢?只是把它們所有選擇出來就已經夠慢了。若是我能夠控制樣式表,那麼就能夠徹底避免這些時間花費了。不過我得告訴你,這個方法是有很大風險的。
風險在於控制樣式表時的跨瀏覽器問題。首先,我嘗試能不能經過jQuery插入一個帶有class的"style"標籤,可是卻出現了跨瀏覽器問題。而後我嘗試用javascript去建立stylesheet節點和class,可是實在有太多的API了,要搞清楚須要花很多的時間。最後,放棄了編程的方式,我在head區裏寫了一個帶有class的style標籤。經過編程的方式來建立stylesheet實在是太慢了,可是若是它一旦被建立好,那麼給它一個ID和使用它的"disabled"屬性就是垂手可得的事情了。
純粹爲了好玩,我想:若是咱們不在每一個dom節點上花功夫,而是去搗鼓樣式表會怎樣呢?這樣會提升速度嗎?其實就平常使用來講,上面的測試用到的方法已經足夠快了,可是若是頁面上有10000個節點須要進行隱藏和顯示呢?只是把它們所有選擇出來就已經夠慢了。若是我能夠控制樣式表,那麼就能夠徹底避免這些時間花費了。不過我得告訴你,這個方法是有很大風險的。
風險在於控制樣式表時的跨瀏覽器問題。首先,我嘗試能不能經過jQuery插入一個帶有class的"style"標籤,可是卻出現了跨瀏覽器問題。而後我嘗試用javascript去建立stylesheet節點和class,可是實在有太多的API了,要搞清楚須要花很多的時間。最後,放棄了編程的方式,我在head區裏寫了一個帶有class的style標籤。經過編程的方式來建立stylesheet實在是太慢了,可是若是它一旦被建立好,那麼給它一個ID和使用它的"disabled"屬性就是垂手可得的事情了。
1  2  3   <style id="special_hide">.special_hide { display: none; }</style>  <!--  ...  -->  <div class="special_hide">Special hide DIV</div>


1   $('#special_hide').attr('disabled, 'true');


1   $('#special_hide').attr('disabled', 'false');

簡要回顧一下,下面是改變元素顯示狀態的方法,按照最快到最慢的次序排列:
  • 禁用/啓用樣式表
  • .css('display', ''), .css('display', 'none')
  • .addClass(), .removeClass()
  • .show(), .hide()
  • .toggle()

.show() 和 .hide()
java

.toggle()
編程

.addClass() 和 .removeClass()
瀏覽器

.css({'display':'none'}) 和 .css({'display':'block'})
緩存

禁止樣式表
dom

而後在javascript裏:ide

搞定!全部帶有"special_hide"這個class的元素都顯示出來了。要隱藏它們,你只須要……性能

如今它們所有都隱藏了。總的javascript耗時在全部瀏覽器上都是0-1ms。你的javascript只是用來改變一個屬性。固然,瀏覽器仍是須要花費時間去從新渲染頁面的,可是實際上你已經避免了javascript的處理時間。若是你調用了.toggle(),.hide()或者.css()這幾個方法,那麼這個方法就會失效。由於那幾個方法會經過內聯方式設置css樣式,這些樣式有更高的優先級。要從新使這個方法生效,只需調用.css('display', '')把內聯的樣式移除掉。這個方法一樣須要花費你更多的精力,由於那須要去定義class,同時把這些class賦給頁面上須要進行顯示/隱藏的元素,可是若是你所要處理的元素數量是極其龐大的話,那麼這也許是值得的。
測試

須要注意的是,在大多數的狀況下,這些方法都足夠的快了。當你要操做很大的jQuery集合時,那麼.show() 和.hide()方法在IE下就會變得很慢了,這是你可能要用addClass() 或者 .removeClass()方法。禁用/啓用樣式表的方法只有在很極端的狀況下才有必要用到

相關文章
相關標籤/搜索