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