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://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 listvar 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 oncefor (i = 0; i < 1000; i++) { var selectedItem = $('.listItem' + i); }
正如所想的,我的瀏覽器花費了5066毫秒的時間(5秒多)。因此我修改上述代碼以使用ID而不是class,然後通過ID進行選擇。
代碼如下:
// Create our listvar 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 oncefor (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});