jQuery代碼性能優(yōu)化的10種方法
1、總是使用#id去尋找element.
在jQuery中最快的選擇器是ID選擇器 ($('#someid')). 這是因?yàn)樗苯佑成錇镴avaScript的getElementById()方法。
選擇單個(gè)元素
<div id="content"> <form method="post" action="/"> <h2>Traffic Light</h2> <ul id="traffic_light"> <li><input type="radio" class="on" name="light" value="red" /> Red</li> <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li> <li><input type="radio" class="off" name="light" value="green" /> Green</li> </ul> <input class="button" id="traffic_button" type="submit" value="Go" /> </form> </div>
選擇button的性能不好的一種方式:
var traffic_button = $('#content .button');
取而代之的是直接選擇button:
var traffic_button = $('#traffic_button');
選擇多個(gè)元素
在我們討論選擇多個(gè)元素的時(shí)候,我們真正需要知道的是DOM的遍歷和循環(huán)才是性能低下的原因。為了盡量減少性能損失, 總是使用最近的父ID去尋找。
var traffic_lights = $('#traffic_light input');
2、在Classes前面使用Tags
在jQuery中第二快的選擇器就是Tag選擇器 ($('head')). 而這是因?yàn)樗苯佑成涞絁avaScript的getElementsByTagName()方法。
<div id="content"> <form method="post" action="/"> <h2>Traffic Light</h2> <ul id="traffic_light"> <li><input type="radio" class="on" name="light" value="red" /> Red</li> <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li> <li><input type="radio" class="off" name="light" value="green" /> Green</li> </ul> <input class="button" id="traffic_button" type="submit" value="Go" /> </form> </div>
總是在一個(gè)Class前面加上一個(gè)tag名字(記得從一個(gè)ID傳下來(lái))
var active_light = $('#traffic_light input.on');
注意:在jQuery里Class選擇器是最慢的一個(gè)選擇器;在IE中它循環(huán)整個(gè)DOM??赡艿脑挶M量避免使用它。不要在ID前面 加Tags。例如,它會(huì)因?yàn)槿パh(huán)所有的<div>元素去尋找ID為content的<div>,而導(dǎo)致很慢。
var content = $('div#content');
按照同樣的思路,從多個(gè)ID傳下來(lái)是冗余的。
var traffic_light = $('#content #traffic_light');
3、緩存jQuery對(duì)象
養(yǎng)成保存jQuery對(duì)象到一個(gè)變量上(就像上面的例子)的習(xí)慣。例如,不要這樣做:
$('#traffic_light input.on).bind('click', function(){...}); $('#traffic_light input.on).css('border', '3px dashed yellow'); $('#traffic_light input.on).css('background-color', 'orange'); $('#traffic_light input.on).fadeIn('slow');
取而代之,首現(xiàn)保存jQuery變量到一個(gè)本地變量后,再繼續(xù)你的操作。
var $active_light = $('#traffic_light input.on'); $active_light.bind('click', function(){...}); $active_light.css('border', '3px dashed yellow'); $active_light.css('background-color', 'orange'); $active_light.fadeIn('slow');
提示:使用$前輟表示我們的本地變量是一個(gè)jQuery包集。記住,不要在你的應(yīng)該程序里出現(xiàn)一次以上的jQuery重復(fù)的選擇操作。 額外提示:延遲存儲(chǔ)jQuery對(duì)象結(jié)果。
如果你想在你的程序的其它地方使用jQuery結(jié)果對(duì)象(result object(s)),或者你的函數(shù)要執(zhí)行多次,要把它緩存在一個(gè)全局范圍的對(duì)象里。通過(guò)定義一個(gè)全局容器保存jQuery結(jié)果對(duì)象,就可以在其它的函數(shù)里引用它。
// Define an object in the global scope (i.e. the window object) window.$my ={ // Initialize all the queries you want to use more than once head : $('head'), traffic_light : $('#traffic_light'), traffic_button : $('#traffic_button')}; function do_something(){ // Now you can reference the stored results and manipulate them var script = document.createElement('script'); $my.head.append(script); // When working inside functions, continue to save jQuery results // to your global container. $my.cool_results = $('#some_ul li'); $my.other_results = $('#some_table td'); // Use the global functions as you would a normal jQuery result $my.other_results.css('border-color', 'red'); $my.traffic_light.css('border-color', 'green'); }
4、更好的利用鏈
前面的例子也可以這樣寫:
var $active_light = $('#traffic_light input.on'); $active_light.bind('click', function(){...}) .css('border', '3px dashed yellow') .css('background-color', 'orange') .fadeIn('slow');
這樣可以讓我們寫更少的代碼,使JavaScript更輕量。
5、使用子查詢
jQuery允許我們?cè)谝粋€(gè)包集上附加其它的選擇器。因?yàn)槲覀円呀?jīng)在本地變量里保存了父對(duì)象這樣會(huì)減少以后在選擇器上的性能開銷。
<div id="content"> <form method="post" action="/"> <h2>Traffic Light</h2> <ul id="traffic_light"> <li><input type="radio" class="on" name="light" value="red" /> Red</li> <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li> <li><input type="radio" class="off" name="light" value="green" /> Green</li> </ul> <input class="button" id="traffic_button" type="submit" value="Go" /> </form> </div>
例如,我們可以利用子查詢緩存active和inactive lights以便后面的操作。
var $traffic_light = $('#traffic_light'), $active_light = $traffic_light.find('input.on'), $inactive_lights = $traffic_light.find('input.off');
提示:可以用逗號(hào)隔開一次定義多個(gè)本地變量,這樣可以節(jié)省一些字節(jié)。
6、限制直接對(duì)DOM操作
DOM操作的基本做法是在內(nèi)存中創(chuàng)建DOM結(jié)構(gòu),然后再更新DOM結(jié)構(gòu)。這不是jQuery最好的做法,但對(duì)JavaScript來(lái)講是高效的。直接操作DOM結(jié)構(gòu)性能是低下的。 例如,如果你需要?jiǎng)討B(tài)創(chuàng)建一列元素,不要這樣做:
var top_100_list = [...], // assume this has 100 unique strings $mylist = $('#mylist'); // jQuery selects our <ul> element for (var i=0, l=top_100_list.length; i<l; i++){ $mylist.append('<li>' + top_100_list[i] + '</li>'); }
取而代之,我們希望在插入DOM結(jié)構(gòu)之前先在一個(gè)字符串里創(chuàng)建一套元素。
代碼
var top_100_list = [...], // assume this has 100 unique strings $mylist = $('#mylist'), // jQuery selects our <ul> element top_100_li = ""; // This will store our list items for (var i=0, l=top_100_list.length; i<l; i++){ top_100_li += '<li>' + top_100_list[i] + '</li>'; } $mylist.html(top_100_li);
更快的做法,在插入DOM結(jié)構(gòu)之前我們應(yīng)該總是在一個(gè)父節(jié)點(diǎn)里包含許多元素
var top_100_list = [...], // assume this has 100 unique strings $mylist = $('#mylist'), // jQuery selects our <ul> element top_100_ul = '<ul id="#mylist">'; // This will store our entire unordered list for (var i=0, l=top_100_list.length; i<l; i++){ top_100_ul += '<li>' + top_100_list[i] + '</li>'; } top_100_ul += '</ul>'; // Close our unordered list $mylist.replaceWith(top_100_ul);
如是你照著上面的做了還是對(duì)性能有些迷惑的話,可以參考以下內(nèi)容:
* 試一下jQuery提供的Clone()方法。Clone()方法創(chuàng)建節(jié)點(diǎn)數(shù)的拷貝,隨后你可以在這個(gè)副本中進(jìn)行操作。
* 使用DOM DocumentFragments. As the creator of jQuery points out, 比直接操作DOM性能上更好. 先創(chuàng)建你需要的結(jié)構(gòu)(就像我們上面用一個(gè)字符串做的一樣), 然后使用jQuery的 insert or replace methods.
7、事件委托(又名:冒泡事件)
除非特別說(shuō)明,每一個(gè)JavaScript事件(如click, mouseover 等)在DOM結(jié)構(gòu)樹上都會(huì)冒泡到它的父元素上。如果我們想讓很多elements(nodes)調(diào)用同一個(gè)function這是非常有用的。取而代之的是 你可以只對(duì)它們的父級(jí)綁定一次,而且可以計(jì)算出是哪一個(gè)節(jié)點(diǎn)觸發(fā)了事件,而不是綁定一個(gè)事件監(jiān)聽器到很多節(jié)點(diǎn)上這種效率低下的方式。例如,假如我們要開發(fā) 一個(gè)包含很多input的大型form,當(dāng)input被選擇的時(shí)候我們想綁定一個(gè)class name。像這樣的幫定是效率低下的:
$('#myList li).bind('click', function(){ $(this).addClass('clicked'); // do stuff });
反而,我們應(yīng)該在父級(jí)偵聽click事件。
$('#myList).bind('click', function(e){ var target = e.target, // e.target grabs the node that triggered the event. $target = $(target); // wraps the node in a jQuery object if (target.nodeName === 'LI') { $target.addClass('clicked'); // do stuff } });
父節(jié)點(diǎn)擔(dān)當(dāng)著發(fā)報(bào)機(jī)的工作,可以在觸發(fā)了事件的目標(biāo)element上做一些工作。如果你發(fā)現(xiàn)自己把一個(gè)event listener幫定到很多個(gè)element上,那么你這種做法是不正確的。
8、消除查詢浪費(fèi)
雖然jQuery對(duì)沒有找到任何匹配的elements處理的很好,但是它還是需要花費(fèi)時(shí)間去查找的。如果你的站點(diǎn)有一個(gè)全局的JavaScript,你可能會(huì)把每個(gè)jQuery function都放在 $(document).ready(function(){ // all my glorious code })里。 不要這樣做。只去放一些頁(yè)面上適合用到的function。這樣做最有效的方式是你的模板可以完全控制任何時(shí)候或者地方執(zhí)行JavaScript以內(nèi)聯(lián)腳 本的方式初始化function。例如,在你的“article”頁(yè)面模板里,你可能在body標(biāo)簽關(guān)閉之前包含以下代碼
<script type="text/javascript>mylib.article.init();</script></body& gt;如果你的頁(yè)面模板包含多種有可能在頁(yè)面或者不在頁(yè)面上的模塊,或者為了可視化效果你需要它們稍后再初如化,你應(yīng)該在這些模塊之后立即放置初如化函數(shù)。
<ul id="traffic_light"> <li><input type="radio" class="on" name="light" value="red" /> Red</li> <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li> <li><input type="radio" class="off" name="light" value="green" /> Green</li> </ul> <script type="text/javascript>mylib.traffic_light.init();</script>
你的全局JavaScript庫(kù)看起來(lái)應(yīng)該是這樣的:
var mylib ={ article_page : { init : function() { // Article page specific jQuery functions. } }, traffic_light : { init : function() { // Traffic light specific jQuery functions. } } }
9、遵從$(windows).load
有 一種誘惑會(huì)使jQuery開發(fā)者h(yuǎn)ook所有事情到 $(document).ready 這個(gè)虛偽的事件里。畢竟在大多數(shù)例子里都可以看到這樣使用。雖然$(document).ready 非常有用,它在頁(yè)面呈現(xiàn)時(shí)發(fā)生,雖然其它對(duì)象還在下載中。如果你發(fā)現(xiàn)你的頁(yè)面在下載中停頓,就有可能是$(document).ready 引起的。你可以通過(guò)把jQuery functions幫定到$(window).load事件來(lái)減少下面下載時(shí)的CPU使用率,它是在所有HTML(包括iframe內(nèi)容)都下載完以后才 去調(diào)用所有對(duì)象的。
$(window).load(function(){ // jQuery functions to initialize after the page has loaded. });
多余的功能,如拖拽、幫定可視化效果和動(dòng)畫、預(yù)讀取圖片等,使用這種方法比較好。
10、壓縮JS
雖然和jQuery無(wú)關(guān),但在這里也要提一下。使JavaScript函數(shù)和變量變得可讀是一個(gè)趨勢(shì),這對(duì)開發(fā)者來(lái)講是必不可少的,但對(duì)普通用戶來(lái) 講沒有任何關(guān)系。不用什么借口,是時(shí)候把JS壓縮納入我們的工作流程中來(lái)了。注釋你的代碼,在投放到生產(chǎn)環(huán)境之前找一個(gè)壓縮工具進(jìn)行壓縮。使用 YUICompressor 壓縮你代碼中多余的浪費(fèi)的字節(jié)。根據(jù)我們的經(jīng)驗(yàn),它可以安全的把JavaScript壓縮的盡可能小,而不會(huì)多占用CPU。小提示:為了在 YUICompressor里最大化壓縮,應(yīng)該這樣這樣定義變量(例如:var my_long_variable_name;)
學(xué)習(xí)和最有效的使用jQuery,最好的方法就是去查jQuery的文檔和手冊(cè)了。
以上就是本文的全部?jī)?nèi)容,了解更多jQuery的語(yǔ)法,大家可以查看:《jQuery 1.10.3 在線手冊(cè)》,也希望大家多多支持腳本之家。
相關(guān)文章
bootstrap table sum總數(shù)量統(tǒng)計(jì)實(shí)現(xiàn)方法
這篇文章主要介紹了bootstrap table sum總數(shù)量統(tǒng)計(jì)實(shí)現(xiàn)方法,需要的朋友可以參考下2017-10-10jQuery實(shí)現(xiàn)選項(xiàng)卡切換效果簡(jiǎn)單演示
這篇文章為大家分享了一款jQuery實(shí)現(xiàn)選項(xiàng)卡切換簡(jiǎn)單演示效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2015-12-12基于jquery的點(diǎn)擊鏈接插入鏈接內(nèi)容的代碼
基于jquery的點(diǎn)擊鏈接插入鏈接內(nèi)容的代碼,感覺有bug,解決的朋友可以留言方便更多的朋友2012-07-07jQuery 操作option的實(shí)現(xiàn)代碼
js清空option之前清空option ,我的做法是遍歷現(xiàn)有option,將其每個(gè)子元素都置空即可。2011-03-03jQuery插件slider實(shí)現(xiàn)拖動(dòng)滑塊選取價(jià)格范圍
jquery滑塊(slider)允許用戶從一個(gè)有限的范圍內(nèi)選擇一個(gè)數(shù)值。當(dāng)沿著軌道移動(dòng)滑塊控件時(shí),將顯示一個(gè)表示當(dāng)前值的提示框,用戶可通過(guò)設(shè)置它的屬性來(lái)自定義滑塊。2015-04-04使用jQueryMobile實(shí)現(xiàn)滑動(dòng)翻頁(yè)效果的方法
這篇文章主要介紹了使用jQueryMobile實(shí)現(xiàn)滑動(dòng)翻頁(yè)效果的方法,較為詳細(xì)的分析了jQueryMobile實(shí)現(xiàn)滑動(dòng)翻頁(yè)效果的原理與實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02jQuery計(jì)算文本框字?jǐn)?shù)及限制文本框字?jǐn)?shù)的方法
一個(gè)中文算兩個(gè),一個(gè)符號(hào)或數(shù)字,英文,算一個(gè)。(如果是規(guī)定140個(gè)字,乘以2,那么就是280個(gè))。需要用到Math.ceil方法,因?yàn)樽詈筮€是要除以2來(lái)還原顯示給用戶的字?jǐn)?shù);2016-03-03