你的位置:面向PHP >> 资讯 >> 前端开发 >> JS & jQuery >> 详细内容 在线投稿

jQuery性能规则

热度100票  浏览32次 【共0条评论】【我要评论 时间:2010年2月07日 22:47
文章信息

来源:转载

)I7s1X J7mf0 之前,我们需要担心减少字节数和请求次数以及加载顺序以使页面加载的更快。如今,我们越来越多的注意到一个影响性能的重要组成部分--CPU利用 率。使用 jQuery和其他JavaScript框架,使节点选择和DOM操作变得越来越容易,但如果你不小心使用了一些减少浏览器本身要做的工作的一些做法可能 会带来不好的结果。面向PHP1c}/L6[_ u N'?U

  1. 总是使用#id去寻找element
  2. 在Classes前面使用Tags
  3. 缓存jQuery对象
  4. 更好的利用链
  5. 使用子查询
  6. 限制直接对DOM操作
  7. 事件委托(又名:冒泡事件)
  8. 消除查询浪费
  9. 遵从 $(window).load
  10. 压缩JS
  11. 学习jQuery库

1.总是使用#id去寻找element.

面向PHPE U2DEM(T

 在jQuery中最快的选择器是ID选择器 ($('#someid')). 这是因为它直接映射为JavaScript的getElementById()方法。
;v2?] H"Y mJ0ce0

*L^&f/Y I;U0

选择单个元素

代码
<div id="content">
0Op1l3cr9P)`0w hh0     
<form method="post" action="/">面向PHP@G*gPjk @Q
        
<h2>Traffic Light</h2>面向PHP%F-`2c(Q3A6}-m*}+m
        
<ul id="traffic_light">
I,{D.Y*V2h0             
<li><input type="radio" class="on" name="light" value="red" /> Red</li>
I nus |[ U0             
<li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>面向PHPt(Os^2Mc
            
<li><input type="radio" class="off" name="light" value="green" /> Green</li>面向PHP(M4C V5{ E:cR
        
</ul>面向PHPOW[,ST#cyc
        
<input class="button" id="traffic_button" type="submit" value="Go" />
+k [ o5qGR"{0     
</form>
HTA:J&vd/_0
</div>
面向PHPX5[v b s-[Hk?

选择button的性能不好的一种方式:

#Ru3z!E&T2@C,R)rj0
var traffic_button = $('#content .button');
面向PHP3aibC%P _.C p

取而代之的是直接选择button:面向PHP-H'e\7g2_Q6^
面向PHPmMp|$pSi o X.n

var traffic_button = $('#traffic_button');

选择多个元素面向PHPISQ&w V5SM

/{ OS|)W'M0在我们讨论选择多个元素的时候,我们真正需要知道的是DOM的遍历和循环才是性能低下的原因。为了尽量减少性能损失, 总是使用最近的父ID去寻找面向PHP-jkpNGc

hq!ev:s C&Mr0
var traffic_lights = $('#traffic_light input');

2.在Classes前面使用Tags

面向PHP+lHb3k!x

在jQuery中第二快的选择器就是Tag选择器 ($('head')). 而这是因为它直接映射到JavaScript的getElementsByTagName()方法。
-~T$R;? _!U){0@"n i4N0 面向PHP9r&P5WM#_bS#KD

<div id="content">
P?+f$iqP}v/e0
    <form method="post" action="/">面向PHP?1z9D D&uy `
        
<h2>Traffic Light</h2>面向PHPy9s d r6g O^qDI
        
<ul id="traffic_light">
c2K~N['uwj1A%a0             
<li><input type="radio" class="on" name="light" value="red" /> Red</li>
c ]8]%R1z6w j6|r` E0             
<li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>面向PHP2?skkz)~ri
            
<li><input type="radio" class="off" name="light" value="green" /> Green</li>面向PHPc+{7j9D/Wd%A T\w
        
</ul>
.Bhu9C3k0         
<input class="button" id="traffic_button" type="submit" value="Go" />
9W&_8eY0Bn)Nu0     
</form>面向PHP B#M2acI^
</div>

y3I_6G PJQ^0总是在一个Class前面加上一个tag名字(记得从一个ID传下来)
&jQ;G-\ A3z{ S0 面向PHPt#N U"_,\%OF uJ

var active_light = $('#traffic_light input.on');

_i2l/\]y,['i0注意:在jQuery里Class选择器是最慢的一个选择器;在IE中它循环整个DOM。可能的话尽量避免使用它。不要在ID前面加Tags。例如,它会因为去循环所有的<div>元素去寻找ID为content的<div>,而导致很慢。
`9J1@0mR0 面向PHPB6ypMw HT;S

var content = $('div#content');
面向PHPh t?CK.V&jj

按照同样的思路,从多个ID传下来是冗余的。
h;bz tb0

cs;J#G?S o.h}%D0
var traffic_light = $('#content #traffic_light');

3.缓存jQuery对象面向PHP(t3fS^,~7qp)k9^

面向PHPm;[ TVO

养成保存jQuery对象到一个变量上(就像上面的例子)的习惯。例如,不要这样做:面向PHP,a _:F|-Hq2W$i

2{7JA Y~Xs$sr?0
$('#traffic_light input.on).bind('click', function(){...});
n%wo/_ tm0~BqGG0 $(
'#traffic_light input.on).css('border''3px dashed yellow');面向PHP,D|oBo.]lf&Q'o
$(
'#traffic_light input.on).css('background-color''orange');
R-N!LQ2~U#n1a;^Q0 $(
'#traffic_light input.on).fadeIn('slow');

|`'MYc:kp/K0P/F0取而代之,首现保存jQuery变量到一个本地变量后,再继续你的操作。
:P$M/e n D0Z{;^.QL0

iw;?Q,H}U!L0
var $active_light = $('#traffic_light input.on');面向PHPR'BW!U%T:[V2ED @
$active_light.bind(
'click'function(){...});面向PHP7}s4sC5n JI Z5@r
$active_light.css(
'border''3px dashed yellow');
8`'R7vy0|)FH;q0 $active_light.css(
'background-color''orange');面向PHP!u:r J?KV
$active_light.fadeIn(
'slow');
面向PHP$KWM}Q#S'wtw

提示:使用$前辍表示我们的本地变量是一个jQuery包集。记住,不要在你的应该程序里出现一次以上的jQuery重复的选择操作。面向PHPO)t1XK_ k

3Tk,\6t }$w0

 额外提示:延迟存储jQuery对象结果。

面向PHP2cB\[&F#w4M`-h$X v

如果你想在你的程序的其它地方使用jQuery结果对象(result object(s)),或者你的函数要执行多次,要把它缓存在一个全局范围的对象里。通过定义一个全局容器保存jQuery结果对象,就可以在其它的函数里引用它。 面向PHP#_]:EpZWR
面向PHPYD*z'hB[|D

// Define an object in the global scope (i.e. the window object)
/w*tO4e)An4N5r0
window.$my =面向PHP+mK6Il@P6B6s
{
F#}V.Sh:K{D"w0     
// Initialize all the queries you want to use more than once
3Op0xW@]-C0
    head : $('head'),面向PHP(NQ{6e0XPZ
    traffic_light : $(
'#traffic_light'),
"ed{qlJ!_0     traffic_button : $(
'#traffic_button')面向PHP-Y Xw-b;x9]%N
};
(~ mE s/@-V'W0
&S zCXC3]k]l0
function do_something()面向PHPh)E9n&W {AV(s v*B
{
~tK\.JBq0     
// Now you can reference the stored results and manipulate them
a%^ AQ5^0
    var script = document.createElement('script');
dH5k.f?N4~)V0     $my.head.append(script);面向PHP0@V;FY'K't~
面向PHP#y&}5GrHu
    
// When working inside functions, continue to save jQuery results
OS\v9B&H6_0
    // to your global container.面向PHPG.V2UC3x U5ae
    $my.cool_results = $('#some_ul li');面向PHP1u"pt4E ^!]kc
    $my.other_results 
= $('#some_table td');面向PHP[vA dZx&o j

)N?ai(iKvG g Bw0     
// Use the global functions as you would a normal jQuery result
zWT7df&i8]0
    $my.other_results.css('border-color''red');
c&B HdU.V"OV0     $my.traffic_light.css(
'border-color''green');
T|(IWH+hN0 }

4.更好的利用链
6r"T2do MLf&e[k;kjg0

0`)X uLk~9w ]y0 前面的例子也可以这样写:

!A5W CKY0Q H0
var $active_light = $('#traffic_light input.on');$active_light.bind('click'function(){...})面向PHP+g.`&W!_`qw3m
    .css(
'border''3px dashed yellow')
L ]Ah ^,P0     .css(
'background-color''orange')
C?s*@!I&M0     .fadeIn(
'slow');

k\8\ y n2BD{*m7d0这样可以让我们写更少的代码,使JavaScript更轻量。面向PHP0o[1I:K,? qM
面向PHP&a&V,]-lrOb

5.使用子查询

pD!s1n-B0jQuery允许我们在一个包集上附加其它的选择器。因为我们已经在本地变量里保存了父对象这样会减少以后在选择器上的性能开销。面向PHPQ0V@ n*Yp
面向PHPSQ*L0p5\"H,W

<div id="content">面向PHPP'A1X+}!?0^PSI
    
<form method="post" action="/">面向PHP0v&j#Q XQ[
        
<h2>Traffic Light</h2>面向PHPZN'Q ~1GmHE;q
        
<ul id="traffic_light">
+Ihi'P IA1_1s0             
<li><input type="radio" class="on" name="light" value="red" /> Red</li>面向PHP;T i_L#M.im
            
<li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>面向PHP \9E:VS;mv*PE
            
<li><input type="radio" class="off" name="light" value="green" /> Green</li>
^yx.j`*z0         
</ul>
U J ~(T)G+r i0         
<input class="button" id="traffic_button" type="submit" value="Go" />面向PHPeD%kr#S
    
</form>面向PHPJ1Y*W#v6~#RD
</div>
面向PHPG:j!l~`

例如,我们可以利用子查询缓存active和inactive lights以便后面的操作。
:K9@4fM FG$t8i0

#]f;d J)Cv0
var $traffic_light = $('#traffic_light'),面向PHPkWL q/? o[
    $active_light 
= $traffic_light.find('input.on'),面向PHPc Ea*^@m[
    $inactive_lights 
= $traffic_light.find('input.off');

/n$UA*Z[%gJ2G1G0提示:可以用逗号隔开一次定义多个本地变量,这样可以节省一些字节。面向PHP1pO+a-v2Vr@Tq
面向PHPv!|}&KZl!J8\

 6.限制直接对DOM操作

&f} d-i V'[0i0DOM操作的基本做法是在内存中创建DOM结构,然后再更新DOM结构。这不是jQuery最好的做法,但对JavaScript来讲是高效的。直接操作DOM结构性能是低下的。 例如,如果你需要动态创建一列元素,不要这样做:
GU_ZEIf;iXc0 面向PHP)A!`'m9m8ojD

var top_100_list = [...], // assume this has 100 unique strings
"p;b{"[ M1J$q!b0
    $mylist = $('#mylist'); // jQuery selects our <ul> element面向PHPCR+YB!i"i8S_.LW

GHK M!a{0
for (var i=0, l=top_100_list.length; i<l; i++)面向PHP(f:qv+tf
{
U]:_~C R9H4C0     $mylist.append(
'<li>' + top_100_list[i] + '</li>');
a u%Uv&YEtfh-f0 }

I-D^[;n&^5U0取而代之,我们希望在插入DOM结构之前先在一个字符串里创建一套元素。
;z#o~\_r)Y0面向PHP m4I)i%FG

var top_100_list = [...], // assume this has 100 unique strings
1yI&]~D-@Y0
    $mylist = $('#mylist'), // jQuery selects our <ul> element面向PHP!J~ l.Q$v~s V"k
    top_100_li = ""// This will store our list items
"L{ |(u&i&D,Q0
面向PHP?"R0u v O/]-L
for (var i=0, l=top_100_list.length; i<l; i++)面向PHP `F|-Z!ztA9t
{
G'H"_ C zp0     top_100_li 
+= '<li>' + top_100_list[i] + '</li>';面向PHP0P0Q{`O Kp8x f
}面向PHPc%m{],pI(Q4i6f
$mylist.html(top_100_li);
面向PHP AI:P2Zo |C+Hq

更快的做法,在插入DOM结构之前我们应该总是在一个父节点里包含许多元素
9o;W0p{Ie0面向PHPIlB0_)p[

var top_100_list = [...], // assume this has 100 unique strings
)r&Vt/P r(sf#k1K0
    $mylist = $('#mylist'), // jQuery selects our <ul> element
m:]5pl2[0`p0
    top_100_ul = '<ul id="#mylist">'// This will store our entire unordered list面向PHP)j$j:W8Snl{-\Y

rBS@1^p*jw s0
for (var i=0, l=top_100_list.length; i<l; i++)
YipPFs}5n4H0 {面向PHPg[JSDo*b XFB
    top_100_ul 
+= '<li>' + top_100_list[i] + '</li>';
'M6Mp8rD!Q7g5x0 }
UY L3Y2p6R)rA P0 top_100_ul 
+= '</ul>'// Close our unordered list面向PHPwK#yz;~6^)l?
面向PHP"C'VF-}v7F
$mylist.replaceWith(top_100_ul);
面向PHPZ6~a6Xv|.`

如是你照着上面的做了还是对性能有些迷惑的话,可以参考以下内容:面向PHPCb1^:SZ~A!D
面向PHP |$Bu:hk"?

7. 事件委托(又名:冒泡事件)
I)O:PZU6@ g1}0

]&](c`I0除非特别说明,每一个JavaScript事件(如click, mouseover 等)在DOM结构树上都会冒泡到它的父元素上。如果我们想让很多elements(nodes)调用同一个function这是非常有用的。取而代之的是 你可以只对它们的父级绑定一次,而且可以计算出是哪一个节点触发了事件,而不是绑定一个事件监听器到很多节点上这种效率低下的方式。例如,假如我们要开发 一个包含很多input的大型form,当input被选择的时候我们想绑定一个class name。像这样的帮定是效率低下的:面向PHP w ?#Toe3n;G S&d\
面向PHP MxP V GJ5k5e

$('#myList li).bind('click', function(){
8VI7G:eW*X'v;N1d0     $(this).addClass(
'clicked');面向PHP ]?K!~%?)du1vu f
    // do stuff面向PHP g @A$k7R$_
});
面向PHP,^L l}"xEP T }$i

反而,我们应该在父级侦听click事件。面向PHP:U*zy"k5f4M

fW0Y*|@/O-E7fJ0
$('#myList).bind('click', function(e){面向PHP6wV^ X7zR6uY[
    var target = e.target, // e.target grabs the node that triggered the event.
@U"K"IJ? P&sC4Z0         $target = $(target);  // wraps the node in a jQuery object
pV-m~;`TC)?0     if (target.nodeName === 
'LI') {
"\g2t1bQ%VD0         $target.addClass(
'clicked');
n7D,m,o"L)Q0         // do stuff面向PHPs)QzA6J%pJ
    }
+uA$D-x?8c z/H2E0 });
面向PHPp{'o:W1XFM2u0j

父节点担当着发报机的工作,可以在触发了事件的目标element上做一些工作。如果你发现自己把一个event listener帮定到很多个element上,那么你这种做法是不正确的。面向PHPD:Z7HsbE k%wr9Q
面向PHP5K+i`M*{g$od7`"Ub

 8.消除查询浪费

面向PHP;W^r5}4T7K8S*`

虽然jQuery对没有找到任何匹配的elements处理的很好,但是它还是需要花费时间去查找的。如果你的站点有一个全局的JavaScript,你可能会把每个jQuery function都放在 $(document).ready(function(){ // all my glorious code })里。 不要这样做。只去放一些页面上适合用到的function。这样做最有效的方式是你的模板可以完全控制任何时候或者地方执行JavaScript以内联脚 本的方式初始化function。例如,在你的“article”页面模板里,你可能在body标签关闭之前包含以下代码面向PHP#Z\~ `o:VLMt@
面向PHP G&_{Cwu;h n

<script type="text/javascript>
*A:J)xk{-c(JHt%N;xS5c0 mylib.article.init();面向PHP)Md2v1C#aq2g7j0w%vj
</script>面向PHPs8E1I?K4u-m2D t
</body>
面向PHP I siE:q6S2yI

如果你的页面模板包含多种有可能在页面或者不在页面上的模块,或者为了可视化效果你需要它们稍后再初如化,你应该在这些模块之后立即放置初如化函数。面向PHPz$jN:fvc3o_/EY ?

s8Q:[o;F#@OZC7D0
<ul id="traffic_light">面向PHP$en+@/f4xN9~!Ys
    
<li><input type="radio" class="on" name="light" value="red" /> Red</li>
1DQu MoV8`,|u5~0     
<li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>
jv"BW5[:HW4Q4Kf0     
<li><input type="radio" class="off" name="light" value="green" /> Green</li>面向PHP3i]4_%u1}p
</ul>面向PHP Iq"[1SXq
<script type="text/javascript>面向PHP/vw E?:nl5G
mylib.traffic_light.init();面向PHP,NO0vw/VPw!g
</script>

j+w&k\ \:GLs ~0你的全局JavaScript库看起来应该是这样的:面向PHP w~7s2Z8H)o

$I!g7w!@5_$q$I0
var mylib =面向PHP/q GoFh3M
{
K%D(TR9F ~we!L0     article_page :
Uq)j4]n*wSF8l0     {面向PHP |~;Do%y*o:Kg4H
        init : 
function()面向PHP'L V:q)FN8_K R
        {面向PHP?*]-v~7WDn(bo
            
// Article page specific jQuery functions.面向PHP'q_#uXK
        }面向PHPR(P+rz#J ?\6}7}
    },面向PHP3~X.F&O%V vi M
    traffic_light :面向PHP[&dSM Mv'Ml
    {
~R#AD_;k0         init : 
function()
%[Kq/p/N.NU0         {面向PHP? _9v1v&X
            
// Traffic light specific jQuery functions.面向PHP#_7F?XDK3Ud
        }面向PHPY)yDD3Q!t
    }面向PHP$b?h1?A!q'o
}

9 遵从$(windows).load面向PHP:?a9X E2sBx4x

_,X5n!c6Z \| t~0有一种诱惑会使jQuery开发者hook所有事情到 $(document).ready 这个虚伪的事件里。毕竟在大多数例子里都可以看到这样使用。虽然$(document).ready 非常有用,它在页面呈现时发生,虽然其它对象还在下载中。如果你发现你的页面在下载中停顿,就有可能是$(document).ready 引起的。你可以通过把jQuery functions帮定到$(window).load事件来减少下面下载时的CPU使用率,它是在所有HTML(包括iframe内容)都下载完以后才去调用所有对象的。
\b%L Q|?NhC0 面向PHP*XRI)H4X

$(window).load(function(){面向PHP TUrP y
    
// jQuery functions to initialize after the page has loaded.
s#k2o-| x/yn0
});
面向PHP^$^C#uuT3I

多余的功能,如拖拽、帮定可视化效果和动画、预读取图片等,使用这种方法比较好。
c\*_G2z+B1z|0 面向PHP/M'w0`Bs*S }u4b

10 压缩JS

9yRsg$s fG%u UZ0虽然和jQuery无关,但在这里也要提一下。使JavaScript函数和变量变得可读是一个趋势,这对开发者来讲是必不可少的,但对普通用户来 讲没有任何关系。不用什么借口,是时候把JS压缩纳入我们的工作流程中来了。注释你的代码,在投放到生产环境之前找一个压缩工具进行压缩。使用YUICompressor 压缩你代码中多余的浪费的字节。根据我们的经验,它可以安全的把JavaScript压缩的尽可能小,而不会多占用CPU。小提示:为了在YUICompressor里最大化压缩,应该这样这样定义变量(例如:var my_long_variable_name;)
:Y9Z E,O+|6s0

2w)lo$A ~)`3y0

11 学习jQuery库

学习jQuery最好的方法就是去查jQuery的文档了,可以当作手册来用。
W*] F AP4e&[0【如果发现页面错乱,可以直接查看原文或者到膘叔的博客去看看http://www.neatstudio.com/show-1097-1.shtml】面向PHPNE(m2Ib)DP5h
TAG: jQuery 性能 规则
顶:9 踩:12
对本文中的事件或人物打分:
当前平均分:-0.59 (29次打分)
对本篇资讯内容的质量打分:
当前平均分:-0.71 (24次打分)
【已经有26人表态】
5票
感动
2票
路过
1票
高兴
4票
难过
4票
搞笑
3票
愤怒
2票
无聊
5票
同情
上一篇 下一篇
发表评论

网友评论仅供网友表达个人看法,并不表明本网同意其观点或证实其描述。

查看全部回复【已有0位网友发表了看法】