讀古今文學網 > 鋒利的jQuery(第2版) > 第11章 jQuery性能優化和技巧 >

第11章 jQuery性能優化和技巧

jQuery越來越流行了,大家可能會發現,在瀏覽網站的過程中,越來越多的網站開始使用jQuery來構建以往需要靠Flash來實現的超酷動態效果,事實上jQuery已經是前端開發中重要的類庫之一,也成為構建豐富Web前端的利器。但是作為一個JavaScript類庫,很多人並不是很清楚如何正確使用jQuery來達到最佳的性能,如果你覺得代碼書寫對於性能的影響不會那麼巨大,那麼我只能告訴你,當你使用jQuery開發一個複雜的動畫和Web應用時,它有可能成為你性能上的終極噩夢。

在本章中,我們將介紹在書寫代碼時,應該需要注意的幾個性能問題,希望對於大家在書寫高性能的Web應用中有所幫助。

11.1 jQuery性能優化

1.使用最新版本的jQuery類庫

jQuery每一個新的版本都會較上一版進行Bug修復和一些優化,同時也會包含一些創新,所以建議使用最新版本的jQuery來提高性能。不過你需要注意的是,在更換版本之後,不要忘記測試你的代碼,畢竟有時候不是完全向後兼容的。

2.使用合適的選擇器

jQuery提供給開發人員非常豐富的手段來使用選擇器定位DOM元素,它是開發人員最常使用的功能,但是很少有開發人員會考慮使用不同的選擇器來處理性能問題。這裡我們將介紹幾種常用的選擇器,及其它們之間的性能差異。

 $(「#id」)

使用id來定位DOM元素無疑是最佳提高性能的方式,因為jQuery底層將直接調用本地方法document.getElementById。熟悉JavaScript的人,都瞭解這個方法將直接通過元素id來返回對應的

元素。當然,如果這個方式不能直接找到你需要的元素,那麼你可以考慮調用find方法。代碼如下:

使用以上代碼可以有效的縮小你定位的DOM元素。為了提高性能,建議從最近的ID元素開始往下搜索。

 $(\"p\"), $(\"p\"), $(\"input\")

標籤選擇器的性能也是不錯的,它是性能優化的第二選擇,因為jQuery將直接調用本地方法document.getElementsByTagName來定位DOM元素。

 $(\".class\")

這種方法較我們來說有些許複雜。對於比較新的瀏覽器例如IE 9,它支持本地方法document.getElementsByClassName,而對於老的瀏覽器,例如IE 8或者更早版本,只能靠使用DOM搜索

方式來實現,這無疑對性能產生較大的影響。所以建議大家有選擇性的使用它。

 $(\"[attribute=value]\")

對於利用屬性來定位DOM元素,本地JavaScript方法中並沒有直接地實現,大多都是使用DOM搜索方式來達到效果,很多現代瀏覽器支持querySelectorAll方法,但是不同瀏覽器間的性能還是有區別。總體來說,使用這種方式來定位DOM元素,性能並不是非常理想。所以為了獲得更好的優化效果,建議開發中盡量避免這種對性能有害的方式。

 $(\":hidden\")

和上面利用屬性來定位DOM的方式類似,這種偽選擇器也同樣沒有直接在本地JavaScript方法中實現,並且jQuery需要搜索每一個元素來定位這個選擇器,這將對你的應用帶來比較大的性能問題。所以建議大家盡量不要使用。如果你堅持使用這種方式,請先使用ID選擇器定位父元素,然後再使用該選擇器,這樣對性能優化會有幫助。代碼如下:

以上是使用選擇器的基本規則,性能自上而下依次下降,如果大家在開發中使用選擇器,請遵循以上這個簡單的優化性能規則。當然,如果覺得不是非常可信,那麼我建議大家使用一個在線工具jsPerf來直觀的查看性能區別,地址:http://jsperf.com/id-vs-class-vs-tag-selectors/2

注意:1.盡量使用ID選擇器。

2.盡量給選擇器指定上下文。

3.緩存對像

在書寫jQuery代碼中,開發人員經常喜歡用如下書寫方式:

當然,編程中的跳躍思維導致你有可能這樣書寫代碼,這無可厚非,但是這樣導致的結果是:jQuery會在創建每一個選擇器的過程中,查找DOM,創建多個jQuery對象。比較好的書寫方式如下:

在本例中,如果使用鏈式方式將更加簡潔,但是這裡只為說明使用緩存變量的重要性,這和Java開發中不要隨意的創建對像一樣,可以幫助你有效的提高代碼運行性能。

上面代碼可以使用jQuery的鏈式操作再加以改善。如下所示:

如果你打算在其他函數中使用jQuery對象,那麼你可以把它們緩存到全局環境中。如下代碼所示:

記住,永遠不要讓相同的選擇器在你的代碼裡出現多次。

4.循環時的DOM操作

使用jQuery可以很方便的添加,刪除或者修改DOM節點,但是在一些循環,例如for,while或者$.each中處理節點時,下面有個實例值得大家注意,代碼如下:

以上代碼中,我們將每一個新添加的標籤元素都作為一個節點添加容器ID中,實際上jQuery操作消耗的性能也不低,所以更好的方式是盡可能的減少DOM操作,這裡應該將整個元素字符串在插入DOM之前全部創建好,修改代碼如下:

記得以前有一個同事也寫過類似的代碼,代碼如下:

看出問題所在了吧,居然把#mylist循環獲取了100次!

5.數組方式使用jQuery對像

使用jQuery選擇器獲取結果是一個jQuery對象。然而,jQuery類庫會讓你感覺你正在使用一個定義了索引和長度的數組。在性能方面,建議使用簡單for或者while循環來處理,而不是$.each,這樣能使你的代碼更快。

使用for代替each方法,代碼如下:

另外注意,檢查長度也是一個檢查jQuery對象是否存在的方式,下面一段代碼通過length屬性檢查頁面中是否含有id為「content」元素:

6.事件代理

每一個JavaScript事件(例如:click, mouseover等)都會冒泡到父級節點。當我們需要給多個元素調用同個函數時這點會很有用。比如,我們要為一個表格綁定這樣的行為:點擊td後,把背景色設置為紅色,代碼如下:

假設有100個td元素,在使用以上方式的時候,你綁定了100個事件,這將帶來很負面的性能影響。那麼有什麼更好的方式呢?

代替這種效率很差的多元素事件監聽的方法就是,你只需向它們的父節點綁定一次事件,然後通過event.target獲取到點擊的當前元素,代碼如下:

在改進方式中,你只為一個元素綁定了1個事件。顯然,這種方式的性能要優於之前那種。同時,在jQuery 1.7中提供了一個新的方式on,來幫助你將整個事件監聽封裝到一個便利方法中,如下所示:

7.將你的代碼轉化成jQuery插件

如果你每次都需要花上一定的時間去開發類似的jQuery代碼,那麼你可以考慮將代碼變成插件。它能夠使你的代碼有更好的重用性,並且能夠有效的幫助你組織代碼。創建一個插件代碼如下:

8.使用join來拼接字符串

也許你之前一直使用」+」來拼接長字符串,現在你可以改改了。雖然它可能會有點奇怪,但它確實有助於優化性能,尤其是長字符串處理的時候。

首先創建一個數組,然後循環,最後使用join把數組轉化為字符串,代碼如下:

9.合理利用HTML5的Data屬性

HTML 5的data屬性可以幫助我們插入數據,特別是前後端的數據交換。jQuery的data方法,有效的利用HTML5的屬性,來自動得到數據。下面是個例子:

為了讀取數據,你需要使用如下代碼:

10.盡量使用原生的JavaScript方法

下面一段代碼,它用來判斷多選框是否被選中:

它使用了jQuery提供的is方法來判斷多選框是否選中,但這裡可以直接使用原生的JavaScript方法,看下面代碼:

毋庸置疑,第二種方式效率高於第一種方式,因為它不需要拐彎抹角的去調用許多函數。

還有更多類似的操作。把如下代碼:

優化成:

把如下代碼:

優化成:

經驗告訴我們,方法的選擇很重要,有時候你也許根本不需要jQuery。

11.壓縮JavaScript

現在的Web項目總是離不開大量JavaScript,而JS文件的體積越來越大,隨之也影響到頁面的感知性能。因此,需要對JavaScript文件進行壓縮,一方面是使用Gzip;另一方面則是去除JavaScript文件裡的註釋、空白,並且壓縮局部變量長度等。對於一些成熟的類庫來說,它們本身都會提供「完整版」和「壓縮版」兩個版本。當我們需要自己修復類庫裡的Bug,這時只能在完整版中修改,對於壓縮版自然就無能為力了。此外,自己寫的JavaScript文件也需要壓縮。

壓縮JavaScript的工具有很多,你可以使用老牌的JSMin, YUI Compressor,它們都可以用來壓縮腳本文件(後者還可以處理CSS),也可以使用一些新的工具,比如Google Closure Compiler和UglifyJS。

11.2 jQuery技巧

如今,越來越多的人在使用jQuery類庫。這也意味著,需要越來越多有用的jQuery技巧和解決方案。下面是我整理的一些實用的jQuery技巧。

1.禁用頁面的右鍵菜單

2.新窗口打開頁面

3.判斷瀏覽器類型

需要注意的是,在jQuery 1.3版本之後,官方推薦使用$.support來代替$.browser這種檢測方式。

4.輸入框文字獲取和失去焦點

5.返回頭部滑動動畫

6.獲取鼠標位置

7.判斷元素是否存在

8.點擊p也可以跳轉

9.根據瀏覽器大小添加不同的樣式

10.設置p在屏幕中央

11.創建自己的選擇器

12.關閉所有動畫效果

13.檢測鼠標的右鍵和左鍵

14.回車提交表單

15.設置全局Ajax參數

16.獲取選中的下拉框

17.切換復選框

18.使用siblings來選擇同輩元素

19.個性化鏈接

20.在一段時間之後自動隱藏或關閉元素

21.使用Firefox和Firebug來記錄事件日誌

22.為任何與選擇器相匹配的元素綁定事件

23.使用css鉤子

jQuery.cssHooks是1.4.3新增的方法,當你定義新的CSS Hooks時實際上定義的是getter和setter方法,比如,border-radius這個圓角屬性想要成功應用於firefox、webkit等瀏覽器,需要增加屬性前綴,比如-moz-border-radius和-webkit-border-radius。你可以通過定義CSS Hooks將其封裝成統一的接口borderRadius,而不是一一設置css屬性。代碼如下:

更多cssHooks可以查看https://github.com/brandonaaron/jquery-cssHooks。

24.$.proxy的使用

使用回調方法的缺點之一是當執行類庫中的方法後,上下文對像被設置到另外一個元素,比如:

執行下面代碼:

你將遇到問題,button元素會消失,而不是panel元素。可以使用$.proxy方法解決這個問題,代碼如下:

這樣才正確的執行。

25.限制Text-Area域中的字符的個數

26.本地存儲

本地存儲是HTML 5提供的特性之一。它提供了非常簡單的API接口,便於添加你的數據到localStorage全局屬性中,代碼如下:

事實上對於老的瀏覽器來說,這並不是個好消息,因為他們不支持,但是我們可以使用jQuery的插件(http://plugins.jquery.com/plugin-tags/localstorage)來提供支持,這種方式可以使得本地存儲功能正常工作。

27.解析json數據時報parseError錯誤

jQuery在1.4版本後,採用了更為嚴格的json解析方式,即所有內容都必須要有雙引號,如果升級jQuery版本後,ajax加載json報錯,有可能就是這個原因。比如:

但升級成jQuery 1.4後,都必須加上雙引號,格式如下:

28.從元素中除去HTML

29.擴展String對象的方法

11.3 小結

本章主要講解了兩部分內容,jQuery性能優化和技巧,相信這些能在實際操作中會有非常大的幫助。

如今,互聯網已經發生翻天覆地的變化,Ajax、模板引擎和MVC開發等一些新型的Web應用正倍受開發者的青睞,與此同時,用戶的需求也越來越高。JavaScript作為增強交互的腳本語言也越來越受到重視,而jQuery作為一個JavaScript腳本庫,相信前途也是一片光明。

未來掌握在自己手中,祝讀者朋友早日成為一名真正的Web前端開發工程師。