1、正確引用jQuery
-
儘量在body結束前才引入jQuery,而不是在head中。
-
藉助第三方提供的CDN來引入jQuery,同時注意當使用第三方CDN出現問題時,要引入本地的jQuery文件。
-
如果在</body>前引入script文件的話,就不用寫document.ready了,因爲這時執行js代碼時DOM已經加載完畢了。
<body>
<script src="http://lib.sinaapp.com/js/jquery11/1.8/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="jquery1.8.min.js">\x3C/script>')</script>
</body>
2、優化jQuery選擇器
高效正確的使用jQuery選擇器是熟練使用jQuery的基礎,而掌握jQuery選擇器需要一定的時間積累,我們開始學習jQuery時就應該注意選擇器的使用。
<div id="nav" class="nav">
<a class="home" href="http://www.jquery001.com">jQuery學習網</a>
<a class="articles" href="http://www.jquery001.com/articles/">jQuery教程</a>
</div>
如果我們選擇class爲home的a元素時,可以使用下邊代碼:
$('.home'); //1
$('#nav a.home'); //2
$('#nav').find('a.home'); //3
方法1,會使jQuery在整個DOM中查找class爲home的a元素,性能可想而知。
方法2,爲要查找的元素添加了上下文,在這裏變爲查找id爲nav的子元素,查找性能得到了很大提升。
方法3,使用了find方法,它的速度更快,所以方法三最好。
關於jQuery選擇器的性能優先級,ID選擇器快於元素選擇器,元素選擇器快於class選擇器。因爲ID選擇器和元素選擇器是原生的JavaScript操作,而類選擇器不是,大家順便可以看下find context 區別,find() children區別。
2.1、一些規則
-
CSS解析引擎將自右向左計算每一條規則,它從關鍵選擇器開始,自右向左計算每一個選擇器,直到發現一個匹配的選擇器,如果沒有找到匹配的選擇器則放棄查找。
-
使用較低層的規則通常更有效率。
-
儘可能的具體化的選擇器——ID要比tag更好。
-
避免不必要的冗餘。
通常請情況下,請保持選擇器簡單明瞭(比如充分使用ID選擇器),儘可能的使用關鍵選擇器更具體,無論對JavaScript還是CSS,這都可以加塊網站的速度。到目前爲止,無論使用哪一種瀏覽器,使用ID選擇器和當個類選擇器都是選中元素最快的方式。
2.2、避免多個ID選擇符
Id選擇符應該是唯一的,所以沒有必要添加額外的選擇符。
// 糟糕
$('div#myid');
$('div#footer a.myLink');
// 建議
$('#myid');
$('#footer .myLink');
在此強調,ID 選擇符應該是唯一的,不需要添加額外的選擇符,更不需要多個後代ID選擇符。
// 糟糕
$('#outer #inner');
// 建議
$('#inner');
2.3、避免隱式通用選擇符
通用選擇符有時是隱式的,不容易發現。
// 糟糕
$('.someclass :radio');
// 建議
$('.someclass input:radio');
2.4、避免通用選擇符
將通用選擇符放到後代選擇符中,性能非常糟糕。
// 糟糕
$('.container > *');
// 建議
$('.container').children();
2.5、選擇捷徑
精簡代碼的其中一種方式是利用編碼捷徑。
// 糟糕
if(collection.length > 0){..}
// 建議
if(collection.length){..}
2.6、爲選擇器指定上下文
默認情況下,當把一個選擇器傳遞給jQuery時,它將遍歷整個DOM,jQuery方法還具有一個未充分利用的參數,既可以將一個上下文參數傳入jQuery,以限制它只搜索DOM中特定的一部分。
//糟糕,會遍歷整個DOM
$(".class");
//建議,只搜索#id元素下的class,id指明搜索範圍
$(".class","#id");
jQuery選擇器的性能比較:
$(".class","#id") > $("#id .class") > $(".class")
3、緩存jQuery對象
緩存jQuery對象可以減少不必要的DOM查找,關於這點大家可以參考下緩存jQuery對象來提高性能。
// 糟糕
h = $('#element').height();
$('#element').css('height',h-20);
// 建議
$element = $('#element');
h = $element.height();
$element.css('height',h-20);
3.1、使用子查詢緩存的父元素
正如前面所提到的,DOM遍歷是一項昂貴的操作。典型做法是緩存父元素並在選擇子元素時重用這些緩存元素。
// 糟糕
var
$container = $('#container'),
$containerLi = $('#container li'),
$containerLiSpan = $('#container li span');
// 建議 (高效)
var
$container = $('#container '),
$containerLi = $container.find('li'),
$containerLiSpan= $containerLi.find('span');
4、變量
4.1、避免全局變量
jQuery與javascript一樣,一般來說,最好確保你的變量在函數作用域內。
// 糟糕
$element = $('#element');
h = $element.height();
$element.css('height',h-20);
// 建議
var $element = $('#element');
var h = $element.height();
$element.css('height',h-20);
4.2、使用匈牙利命名法
在變量前加$前綴,便於識別出jQuery對象。
// 糟糕
var first = $('#first');
var second = $('#second');
var value = $first.val();
// 建議 - 在jQuery對象前加$前綴
var $first = $('#first');
var $second = $('#second'),
var value = $first.val();
4.3、使用 Var 鏈(單 Var 模式)
將多條var語句合併爲一條語句,我建議將未賦值的變量放到後面。
var $first = $('#first'),
$second = $('#second'),
value = $first.val(),
k = 3,
cookiestring = 'SOMECOOKIESPLEASE',
i,
j,
myArray = {};
5、正確使用事件委託
在新版jQuery中,更短的 on(“click”) 用來取代類似 click() 這樣的函數。在之前的版本中 on() 就是 bind()。自從jQuery 1.7版本後,on() 附加事件處理程序的首選方法。然而,出於一致性考慮,你可以簡單的全部使用 on()方法。
<table id="t">
<tr>
<td>我是單元格</td>
</tr>
</table>
比如我們要在上邊的單元格上綁定一個單擊事件,不注意的朋友可能隨手寫成下邊的樣子:
$('#t').find('td').on('click', function () {
$(this).css({ 'color': 'red', 'background': 'yellow' });
});
這樣會爲每個td綁上事件,在爲100個單元格綁定click事件的測試中,兩者性能相差7倍之多,好的做法應該是下邊寫法:
$('#t').on('click', 'td', function () {
$(this).css({ 'color': 'red', 'background': 'yellow' });
});
6、精簡jQuery代碼
如在上述代碼中我們對jQuery代碼進行了適當的合併,類似的還有.attr()方法等,我們沒有寫成下邊的方式:
$('#t').on('click', 'td', function () {
$(this).css('color', 'red').css('background', 'yellow');
});
6.1、合併函數
一般來說,最好儘可能合併函數。
// 糟糕
$first.click(function(){
$first.css('border','1px solid red');
$first.css('color','blue');
});
// 建議
$first.on('click',function(){
$first.css({
'border':'1px solid red',
'color':'blue'
});
});
6.2、鏈式操作
jQuery實現方法的鏈式操作是非常容易的。下面利用這一點。
// 糟糕
$second.html(value);
$second.on('click',function(){
alert('hello everybody');
});
$second.fadeIn('slow');
$second.animate({height:'120px'},500);
// 建議
$second.html(value);
$second.on('click',function(){
alert('hello everybody');
}).fadeIn('slow').animate({height:'120px'},500);
7、減少DOM操作
剛開始使用jQuery時可能會頻繁的操作DOM,這是相當耗費性能的。如我們要在body中動態輸出一個表格,一些朋友會這樣寫:
//糟糕
var $t = $('body');
$t.append('<table>');
$t.append('<tr><td>1</td></tr>');
$t.append('</table>');
//建議
$('body').append('<table><tr><td>1</td></tr></table>');
這樣在拼接完table串後再添加到body中,對DOM的操作只需一次。羣裏以前有朋友就因爲這個導致在IE下輸出時出現問題,而關於字符串的拼接可以參考下最快創建字符串的方法。
7.1、繁重的操作中分離元素
如果你打算對DOM元素做大量操作(連續設置多個屬性或css樣式),建議首先分離元素然後在添加。
// 糟糕
var
$container = $("#container"),
$containerLi = $("#container li"),
$element = null;
$element = $containerLi.first();
//... 許多複雜的操作
// better
var
$container = $("#container"),
$containerLi = $container.find("li"),
$element = null;
$element = $containerLi.first().detach();
//... 許多複雜的操作
$container.append($element);
7.2、最小化DOM更新
重佈局和重繪是WEB頁面中最常見的也是最昂貴的兩種操作。
-
當改變樣式,而不改變頁面幾何佈局時,將會發生重繪。隱藏一個元素或者改變一個元素的背景色時都將導致一次重繪。
-
當對頁面結構進行更新時,將導致頁面重佈局。
//糟糕
for(var i=0; i<10000; i++){
$("#main table").append("<tr><td>aaaa</td></tr>");
}
//建議
var tablerow = "";
for(var i=0; i<10000; i++){
tablerow += "<tr><td>aaaa</td></tr>";
}
$("#main table").append(tablerow);
8、維持代碼的可讀性
伴隨着精簡代碼和使用鏈式的同時,可能帶來代碼的難以閱讀。添加縮緊和換行能起到很好的效果。
// 糟糕
$second.html(value);
$second.on('click',function(){
alert('hello everybody');
}).fadeIn('slow').animate({height:'120px'},500);
// 建議
$second.html(value);
$second
.on('click',function(){ alert('hello everybody');})
.fadeIn('slow')
.animate({height:'120px'},500);
9、選擇短路求值
短路求值是一個從左到右求值的表達式,用 &&(邏輯與)或 ||(邏輯或)操作符。
// 糟糕
function initVar($myVar) {
if(!$myVar) {
$myVar = $('#selector');
}
}
// 建議
function initVar($myVar) {
$myVar = $myVar || $('#selector');
}
10、堅持最新版本
新版本通常更好:更輕量級,更高效。顯然,你需要考慮你要支持的代碼的兼容性。例如,2.0版本不支持ie 6/7/8。
摒棄棄用方法
關注每個新版本的廢棄方法是非常重要的並儘量避免使用這些方法。
// 糟糕 - live 已經廢棄
$('#stuff').live('click', function() {
console.log('hooray');
});
// 建議
$('#stuff').on('click', function() {
console.log('hooray');
});
// 注:此處可能不當,應爲live能實現實時綁定,delegate或許更合適
11、最後忠告
最後,我記錄這篇文章的目的是提高jQuery的性能和其他一些好的建議。如果你想深入的研究對這個話題你會發現很多樂趣。記住,jQuery並非不可或缺,僅是一種選擇。思考爲什麼要使用它。DOM操作?ajax?模版?css動畫?還是選擇符引擎?或許javascript微型框架或jQuery的定製版是更好的選擇。
雖然都是陳詞濫調,但是我發現還不能很好得做到上述所有,記錄下來希望自己能夠全部做到。
12、不使用jQuery
原生函數總是最快的,這點不難理解,在代碼書寫中我們不應該忘記原生JS。就先總結這幾條吧,每條建議並不難理解,但總結全面的話還是要花費不少時間的。如在減少代碼段中,如果需要根據條件從數組中得到新數組時,可以使用$.grep() 方法,如果你在使用jQuery時有自己心得的話,歡迎在留言中和大家分享!
參考資料:
《jQuery高級編程》[Cesar Otero,Rob Larsen],(譯)施宏斌,清華大學出版社,2013年4月第1版
http://mp.weixin.qq.com/s?__b...