改善你的jQuery的25個步驟 千倍級效率提升

來源:互聯網
上載者:User

1. 從Google Code載入jQuery
Google Code上已經託管了多種JavaScript類庫,從Google Code上載入jQuery比直接從你的伺服器載入更有優勢。它節省了你伺服器上的頻寬,能夠很快的從Google的內容分布網路(CDN)上載入JS類庫。更重要的是,如果使用者訪問那些發布在Google Code上的網站後它會被緩衝下來。
這樣做很有意義。有多少網站使用了沒有被緩衝的相同jQuery副本,而這些很容易做到,引入:

<script type="text/javascript" src=" http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>

2. 使用備忘單
不僅僅是jQuery,很多程式設計語言也有類似的備忘單,在一張A4的紙上就可以很容易看到每個函數的用法。幸運的是已經有好心的傢伙把jQuery的備忘單做得很完善了:
http://www.gscottolson.com/weblog/2008/01/11/jquery-cheat-sheet/
http://colorcharge.com/jquery/

3. 整合所有的指令碼並縮減它們
不錯,這是JavaScript的一個常見技巧。可是一個使用了jQuery的大項目可能使用了很多相關的jQuery外掛程式(本站就使用了easing,localScroll,lightbox,preload),因此它通常是適用的。瀏覽器不能同時載入JS指令碼(大多數情況下),這意味著如果你同一時間載入很多指令碼的話,將減緩頁面的載入速度。因此,如果每個頁面都要載入這些指令碼,你應該考慮在發布之前將這些指令碼整合成一個稍大的JS指令碼。一些jQuery外掛程式已經最小化了,但是你應該打包你的JS指令碼和那些沒有縮減過的指令碼,這僅需要幾秒的時間就可以完成。
就個人而言,我推薦Packer by Dean Edwards

4. 使用Firebug出色的控制台日誌工具
如果你還沒有安裝Firebug,那麼你真的應該把它裝上。除了許多其它有用的特性(比如允許你檢查http傳輸情況、發現你的CSS問題),它也有極好的日誌命令,允許你很容易調試JS指令碼。
這裡有Firebug所有特性的詳細說明。
我最喜歡的特性有”console.info“,通過它你可以把資訊和變數值輸出到控制台上,而不必使用alert;”console.time”則允許你在一組代碼上設定定時器,從而計算出JS指令碼運行所花費的時間。這一切都很容易做到:

複製代碼 代碼如下:console.time('create list');
for (i = 0; i < 1000; i++) {
var myList = $('.myList');
myList.append('This is list item ' + i);
}
console.timeEnd('create list');

5. 通過緩衝最小化選擇操作
jQuery的選取器棒極了。它們可以在頁面上以極其簡單的方法找到任何元素,但是在內部它們必須通過大量的步驟才可以實現選擇操作,如果你錯誤的使用它們,那麼你可能發現一切都變得相當慢。
如果你一次又一次的選擇相同元素(例如在一個迴圈中),那麼你可以一次選擇出它並放入記憶體中,同時你可以在核心內容裡操作它。看下面的例子,這裡我們利用迴圈往UL裡添加條目:複製代碼 代碼如下:for (i = 0; i < 1000; i++) {
var myList = $('.myList');
myList.append('This is list item ' + i);
}

這在我的PC上Firefox 3花費了1066毫秒時間(可以設想一下在IE6中的情況!),對JavaScript而言這個操作相當慢。現在讓我們來看看下面的代碼,這裡我們僅使用了一次選擇操作:複製代碼 代碼如下:var myList = $('.myList');
for (i = 0; i < 1000; i++) {
myList.append('This is list item ' + i);
}

僅僅用了224毫秒,通過移動一行代碼就快了將近4倍。

6. 最小化DOM操作
我們通過減少對DOM的插入操作可以讓上面的代碼運行得更快。DOM的插入操作(像.append(),.prepend(),.after(),.wrap())是相當耗時的,執行這些操作會拖慢程式的運行。
我們所要做的就是使用字串拼接來構造一個list項並用一個函數往列表裡添加這些項,比如.html()。請看下面的例子:

複製代碼 代碼如下:var myList = $('#myList');
for (i=0; i<1000; i++){
myList.append('This is list item ' + i);
}

在我的PC上花費了216毫秒,僅僅在1/5秒左右。但是如果我們使用字串構造list項,使用下面的HTML方法完成插入操作: 複製代碼 代碼如下:var myList = $('.myList');
var myListItems = '';
for (i = 0; i < 1000; i++) {
myListItems += '<li>This is list item ' + i + '</li>';
}
myList.html(myListItems);

它耗時185毫秒,儘管沒有快很多,但是也提高了31毫秒的時間。
7. 處理DOM插入操作時,將需要的內容封裝在一個元素中
嗯,不要問我為什麼要這樣做(我相信一個有相當經驗的程式員會給你解釋)。
在上面的例子中我們使用.html()將1000個item項插入到UL中。如果在插入操作之前我們將這些項封裝在UL標籤中,然後把完整的UL插入到另一個DIV標籤中,那麼我們實際上僅僅插入一個標籤而不是1000個,這看起來要更高效些。請看下面這個例子:複製代碼 代碼如下:var myList = $('.myList');
var myListItems = '<ul>';

for (i = 0; i < 1000; i++) {
myListItems += '<li>This is list item ' + i + '</li>';
}
myListItems += '</ul>';
myList.html(myListItems);

現在所花費的時間僅19毫秒,比我們之前的第一個例子明顯提高了50倍。
8. 儘可能使用ID而不是class
jQuery利用classes進行DOM元素選擇操作與通過ID進行選擇一樣容易,因此與之前相比更自由的使用classes進行元素選擇操作很有吸引力。不過由於jQuery使用瀏覽器固有的方法(getElementById )進行選擇操作,因此利用ID進行選擇操作更有優勢。有多快呢?讓我們來看看。
我使用前一個例子,修改它以便於我們建立的每個LI有一個唯一的class。然後我將遍曆之,每次選擇一個元素:複製代碼 代碼如下:// Create our list
var myList = $('.myList');
var myListItems = '<ul>';
for (i = 0; i < 1000; i++) {
myListItems += '<li class="listItem' + i + '">This is a list item</li>';
}
myListItems += '</ul>';
myList.html(myListItems);
// Select each item once
for (i = 0; i < 1000; i++) {
var selectedItem = $('.listItem' + i);
}

正如所想的,我的瀏覽器花費了5066毫秒的時間(5秒多)。因此我修改上述代碼以使用ID而不是class,然後通過ID進行選擇。 複製代碼 代碼如下:// Create our list
var myList = $('.myList');
var myListItems = '<ul>';
for (i = 0; i < 1000; i++) {
myListItems += '<li id="listItem' + i + '">This is a list item</li>';
}
myListItems += '</ul>';
myList.html(myListItems);
// Select each item once
for (i = 0; i < 1000; i++) {
var selectedItem = $('#listItem' + i);
}

僅僅耗時61毫秒,幾乎快了100倍

9. 給選取器提供上下文
預設情況下,當你使用類似$('.myDiv')的選取器時將在整個DOM文檔尋找元素,這有很大的代價。
當執行選擇操作時,jQuery函數可以指定第二個參數:jQuery( expression, context )通過給選取器提供一個上下文,那就會在這個context中進行元素尋找,而不必在整個DOM文檔中尋找元素。
為瞭解釋這個,我們採用前面的第一段代碼。它建立一個有1000項內容的UL,每項都有一個單獨的class。
然後遍曆之每次選擇一項。你應該記得通過class選擇所有的1000項item需要耗時5秒多。

複製代碼 代碼如下:var selectedItem = $('#listItem' + i);

然後我給其添加一個上下文,以便於僅在UL中執行選擇操作: 複製代碼 代碼如下:var selectedItem = $('#listItem' + i, $('.myList'));

由於效率太差,仍耗時3818毫秒的時間,但是通過一個很小的修改仍獲得了25%的速度提升。
10. 正確使用方法鏈
jQuery最炫的一個特性就是jQuery能夠連續的進行方法調用。舉例來說,你想去切換元素的class:複製代碼 代碼如下:$('myDiv').removeClass('off').addClass('on');

如果你像我這樣,你可能在前五分鐘的jQuery學習就可以更進一步使用它。首先它仍可以跨行操作(jQuery是JavaScript) ,這意味著你能夠寫出下面這樣工整的代碼: 複製代碼 代碼如下:$('#mypanel')
.find('TABLE .firstCol')
.removeClass('.firstCol')
.css('background' : 'red')
.append('<span>This cell is now red</span>');

使用鏈表的習慣將有助於你減少選取器的使用。然而可以更深入使用之,你想在一個元素上執行好幾個函數,但是以某種方式改變了操作的元素: 複製代碼 代碼如下:$('#myTable').find('.firstColumn').css('background','red');

我們選擇了一個表格,在其中找到class為”firstColumn”的儲存格,然後使之背景變為紅色。
現在我們希望將所有class為”lastColumn”的儲存格背景設為藍色。因為我們已經使用了find()函數過濾出class不為”firstColumn”的所有儲存格,因此我們需要再一次對錶格使用選擇操作,我們難道不能連續進行方法調用嗎?幸運的是jQuery提供了end()函數,這將匹配的元素列表變為前一次狀態以便於你可以執行方法鏈表: 複製代碼 代碼如下:$('#myTable')
.find('.firstColumn')
.css('background','red')
.end()
.find('.lastColumn')
.css('background','blue');

寫一個能夠進行方法鏈式調用的自訂jQuery函數也很容易。你所做的就是要寫個能修改元素並返回元素的函數。 複製代碼 代碼如下:$.fn.makeRed = function() {
return $(this).css('background', 'red');
}
$('#myTable').find('.firstColumn').makeRed().append('hello');

它很簡單吧!

11. 學會正確使用效果
在我剛開始使用jQuery的時候,就很喜歡這一點:它可以很容易使用預定義好的各種動畫效果,像slideDown()和fadeIn()之類的。由於jQuery提供的animate()方法十分易用和強大,我們很容易深入使用它。事實上,在jQuery原始碼中不少方法就是通過animate()函數來實現效果的。

複製代碼 代碼如下:slideDown: function(speed,callback){
return this.animate({height: "show"}, speed, callback);
},

fadeIn: function(speed, callback){
return this.animate({opacity: "show"}, speed, callback);
}

animate()方法僅僅作用在CSS上,根據數值平滑的進行轉換。因此你能夠改變寬度、高度、透明度、背景色、top、left、margin、顏色、字型大小以及任何你想要的。
給功能表項目添加高度變化的效果是很容易做到的: 複製代碼 代碼如下:$('#myList li').mouseover(function() {
$(this).animate({"height": 100}, "slow");
});

不像其他的jQuery函數,動畫效果自動的排進隊列,因此如果在第一個特效完成之後你想運行第二個特效,需要兩次調用animate方法: 複製代碼 代碼如下:$('#myBox').mouseover(function() {
$(this).animate({ "width": 200 }, "slow");
$(this).animate({"height": 200}, "slow");
});

如果你想動畫效果同時發生,那麼需要將所有的styles作為一個參數對象傳入方法中: 複製代碼 代碼如下:$('#myBox').mouseover(function() {
$(this).animate({ "width": 200, "height": 200 }, "slow");
});

你能夠給值是數位屬性添加動畫效果。你也可以下載外掛程式協助你給非數字值的屬性添加動畫效果,像colors and background colors

12. 瞭解事件代理
與之前相比,jQuery能夠更容易得向DOM元素無縫添加事件。這是很棒的特性,然而向元素添加太多的事件是效率很差的。在很多情況下事件代理允許你用少量的事件實現同樣的目的。最好的解釋方法就是使用執行個體:

複製代碼 代碼如下:$('#myTable TD').click(function(){
$(this).css('background', 'red');
});

當我們點擊表格中的儲存格時,上面的代碼將使所有儲存格背景變為紅色。比方說,你有一個10列、50行的網格,那麼就會綁定上500個事件。嗯,這時就是事件代理出場的時候了: 複製代碼 代碼如下:$('#myTable').click(function(e) {
var clicked = $(e.target);
clicked.css('background', 'red');
});

e'包含了事件的資訊,包括了實際接收到click事件的目標元素。我們所要做的就是檢查是哪個儲存格被點擊了。相當的巧妙!
事件代理帶來了另外一個好處。正常情況下,在你往一個元素集合綁定一個事件,該事件僅僅只是綁定到這些集合元素上。如果你向DOM中添加了新的元素,儘管這些新元素被選取器所匹配,但是這些新元素並不會綁定上事件處理(你同意我的觀點嗎?),因此不會有事件發生。
當使用事件代理時,你能夠在事件被DOM綁定後仍然可以添加多個被匹配的元素到其中,而它們同樣能夠正常工作。
13. 利用classes儲存狀態
這是在html中儲存資訊最基本的方法。jQuery擅長基於classes進行元素的操作,因此如果你需要儲存元素的狀態資訊,為什麼不試試使用額外的class來儲存它呢?
這裡有一個例子。我們想建立一個展開的菜單。當你點擊按鈕時,我們希望通過slideDown()和slideUp()進行菜單的展開與收縮。請看下面的HTML:複製代碼 代碼如下:<div class="menuItem expanded">
<div class="button">
click me
</div>
<div class="panel">
<ul>
<li>Menu item 1</li>
<li>Menu item 2</li>
<li>Menu item 3</li>
</ul>
</div>
</div>

非常的簡單!我們僅僅向封裝器DIV添加一個額外的class,它只是告訴我們item項的狀態。因此在按鈕點擊之後我們所需要的只是click事件處理,這會執行相應的slideUp()和slideDown()方法。 複製代碼 代碼如下:$('.button').click(function() {

var menuItem = $(this).parent();
var panel = menuItem.find('.panel');

if (menuItem.hasClass("expanded")) {
menuItem.removeClass('expanded').addClass('collapsed');
panel.slideUp();
}
else if (menuItem.hasClass("collapsed")) {
menuItem.removeClass('collapsed').addClass('expanded');
panel.slideDown();
}
});

這是很簡單的一個例子,不過你可以給一個元素或HTML片斷添加額外的classes以儲存所有種類的資訊。
然而,除了在簡單的情況之外我們更應該使用下面這個技巧。
14. 更好的方法是利用jQuery內建的data()方法儲存狀態
由於某些原因,這方面沒有很好的文檔可以參考。jQuery提供了內建的data()方法,與DOM元素不同的是,它可以用來儲存key/value類型的資料。資料的儲存是很容易的:複製代碼 代碼如下:$('#myDiv').data('currentState', 'off');

我們修改上一個例子的代碼,以便於我們可以使用相同的HTML內容(除了沒有”expanded”類)並使用data()函數來進行狀態的儲存: 複製代碼 代碼如下:$('.button').click(function() {

var menuItem = $(this).parent();
var panel = menuItem.find('.panel');

if (menuItem.data('collapsed')) {
menuItem.data('collapsed', false);
panel.slideDown();
}
else {
menuItem.data('collapsed', true);
panel.slideUp();
}
});

我相信你也會贊同這種方法的使用的確更加的精巧,對於data()和removeData()的更多資訊,請查看jQuery internals
15. 寫你自己的選取器
jQuery有許多內建的選取器用以通過ID、class、標籤、屬性以及其他元素進行選擇操作。然而當你需要基於其它一些內容進行元素選擇而jQuery卻沒有提供該選取器時,你能做什麼呢?
嗯,一個解決方案可能是從一開始就給元素添加上classes,從而利用這些classes進行元素的選擇操作。然而這被證明很難對jQuery擴充出新的選取器。
最好的解釋方法就是使用執行個體:複製代碼 代碼如下:$.extend($.expr[':'], {
over100pixels: function(a) {
return $(a).height() > 100;
}
});

$('.box:over100pixels').click(function() {
alert('The element you clicked is over 100 pixels high');
});

代碼的前一部分建立一個自訂的選取器,它可以找出所有長度超過100px的元素。接下來的代碼僅僅是將click事件綁定到使用該選取器尋找出來的那些元素上。
這裡我不做更具體的講解,但是你能設想一下它有多麼的強大!如果你在google上搜尋”custom jquery selector”,你會看到有很多這方面的例子。

16. 精簡你的HTML並在頁面載入後修改它
這個標題可能沒有多大意思,但是這個技巧可能理順你的代碼、減小代碼體積和頁面的下載時間、有助最佳化你的搜尋引擎。請看下面的例子:

複製代碼 代碼如下:<div class="fieldOuter">
<div class="inner">
<div class="field">This is field number 1</div>
</div>
<div class="errorBar">
<div class="icon"><img src="icon.png" alt="icon" /></div>
<div class="message"><span>This is an error message</span></div>
</div>
</div>
<div class="fieldOuter">
<div class="inner">
<div class="field">This is field number 2</div>
</div>
<div class="errorBar">
<div class="icon"><img src="icon.png" alt="icon" /></div>
<div class="message"><span>This is an error message</span></div>
</div>
</div>

上面是一個HTML的具體例子,為瞭解釋目的做了少量修改。我相信你也會認為這段代碼相當的醜陋。如果類似代碼很長的話,你最終會形成一個相當長且醜陋的頁面。因此你可以像下面這樣處理它: 複製代碼 代碼如下:<div class="field">This is field 1</div>
<div class="field">This is field 2</div>
<div class="field">This is field 3</div>
<div class="field">This is field 4</div>
<div class="field">This is field 5</div>

所有你要做的就是在頁面載入完成之後通過jQuery的操作將醜陋的HTML添加回去: 複製代碼 代碼如下:$(document).ready(function() {
$('.field').before('<div class="fieldOuter"><div class="inner">');
$('.field').after('</div><div class="errorBar"><div class="icon">
<img src="icon.png" alt="icon" /></div><div class="message">
<span>This is an error message</span></div></div></div>');
});

這樣做並不總是可取的,在頁面載入後的一瞬間你將會看到頁面的閃動,但是在特定情況下你有很多重複的HTML內容,這時通過這個方法你可以顯著的減小頁面代碼體積,減少無關且重複的標記能使你的SEO從中受益。
17. 為了速度和SEO方面的考慮,消極式載入內容
另外還有一個方法可以提升頁面載入速度,理順Spiders搜尋的HTML內容,通過在頁面載入之後使用AJAX請求晚載入其他內容,這樣使用者就可以馬上開始瀏覽,讓Spider看到你想要它們進行索引的內容。
我們已經在自己的網站上使用了這個技術。本頁面上部的紫色按鈕會彈出三個表格,方位與Google地圖,這會使我們頁面大小增加兩倍。因此我們僅需要把這些HTML內容放入一個靜態頁面中,在頁面載入完成之後通過load()函數載入它:複製代碼 代碼如下:$('#forms').load('content/headerForms.html', function() {
// Code here runs once the content has loaded
// Put all your event handlers etc. here.
});

我不會在頁面上隨處使用這個技巧。對此,你必須權衡考慮。你需要有額外的頁面請求,而且頁面上的部分內容不能立即呈現給使用者,但是正確的使用這個技巧對最佳化會很有協助。
18. 使用jQuery提供的工具函數
jQuery不僅僅有閃光的效果。jQuery作者也提供了一些相當實用的方法,這填補了JacaScript的一些缺陷。
http://docs.jquery.com/Utilities
尤其,提供一些常見的數組函數的瀏覽器支援是一個補丁。jQuery提供了迭代、過濾、複製、合并和從數組中去除重複項的方法。
其他常用的函數包括得到下拉框中的選擇項。用傳統的JavaScript方法,你就必須使用getElementById得到<select>元素,然後通過遍曆它的子項目找出被選中的元素。而jQuery提供了相當容易使用的方法:複製代碼 代碼如下:$('#selectList').val();

花時間瀏覽官方網站上的jQuery文檔與一些不常用的方法上是很值得的。
19. 使用noConflict重新命名jQuery對象
大多數JavaScript架構都使用$符號作為縮寫,當在同一個頁面使用多個JS架構時,頁面很容易發生衝突。幸運的是有一個簡單的方法。noConflict()函數交回$的控制權並允許你設定成自己的變數名:複製代碼 代碼如下:$('#selectList').val();

20. 如何得知圖片已載入完畢
這也一個沒有很好文檔說明的問題(至少在我尋找時沒看到),但是在建立照片庫、旋轉燈籠效果等方面,它是相當常見的需求。而這在jQuery中很容易實現。
所有你要做的就是在IMG上使用.load()方法,在其中添加一個回呼函數。下面的例子改變了一個圖片src的屬性同事附加上一個簡單的load函數:複製代碼 代碼如下:$('#myImage').attr('src', 'image.jpg').load(function() {
alert('Image Loaded');
});

你應該可以發現一旦圖片載入完畢就會彈出一個alert。
21. 總是使用最新版本
jQuery仍在不斷的更新,它的作者John Resig一直在尋找提高jQuery效能的方法。jQuery當前的版本是1.3.2,John已經宣稱他正在寫一個新的選取器引擎Sizzle,這可能會顯著的提高選取器效能(在Firefox中提升了4倍),因此我們應當保持最新版本。

22. 如何檢查元素是否存在
你不必檢查元素是否在頁面上存在就可以使用它,因為如果沒有在DOM中找到合適的元素,jQuery什麼也不會做。可是當我們需要檢查元素是否被選擇了,或是有多少項被選擇了,你可以使用length屬性:

複製代碼 代碼如下:if ($('#myDiv).length) {
// your code
}

簡單之極。
23. 給你的HTML 屬性增加JS類
我是從Karl Swedberg那學到這個技巧,過去學習jQuery時一直在看他的書。
他最近在我以前的文章留下了對該用法的評論,基本原則如下示之。
首先,在jQuery載入之後你可以使用方法將”JS”類添加到HTML標籤中:複製代碼 代碼如下:$('HTML').addClass('JS');

因為這僅僅發生在javascript有效時候,如果使用者開啟JavaScript開關,那麼你可以使用它給元素添加上CSS風格: 複製代碼 代碼如下:.JS #myDiv{display:none;}

因此,這意味著在JavaScript開啟時我們可以隱藏內容,然後在需要時使用jQuery顯示這些內容(比如在使用者點擊時收縮或展開內容),同時在關閉JavaScript(以及搜尋Spiders)時會看到所有內容。我將在晚些時候使用這個技巧。
可以在這裡看到他的所有文章。
24. 返回'false'以防止預設行為
這是很明顯的,也可能不是。如果你有這樣的習慣:複製代碼 代碼如下:<a href="#" class="popup">Click me!</a>

然後添加上如下的事件處理: 複製代碼 代碼如下:$('popup').click(function(){
// Launch popup code
});

你在長頁面使用上述方法時,它可能可以正常工作。有些時候你會注意到在點選連結後錨點會跳轉到頁面上部。
所有你要做的就是阻止它的預設行為,或者實際上你可以把”return false;”添加到任何事件的預設行為上。像這樣: 複製代碼 代碼如下:$('popup').click(function(){
// Launch popup code
return false;
});

25. ready事件的簡寫
一個小技巧但是通過使用$(document).ready()的簡寫,你可以少輸入幾個字元。
取代:

複製代碼 代碼如下:$(document).ready(function (){
// your code
});

你可以簡寫成: 複製代碼 代碼如下:$(function (){
// your code
});

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.