提高jquery 性能方法整理

1. 总是从ID选择器开始继承

在jQuery中最快的选择器是ID选择器,因为它直接来自于JavaScript的getElementById()方法。

如果采用下面的选择器,那么效率是低效的。

var traffic_button = $(“#content .button”);

因为button已经有ID了,我们可以直接使用ID选择器。如下所示:

 var traffic_button = $(“#traffic_button”);

 当然 这只是对于单一的元素来讲。如果你需要选择多个元素,这必然会涉及到 DOM遍历和循环,
为了提高性能,建议从最近的ID开始继承。
如下所示:

var content = $(”div#content”);
     var traffic_lights = $(”#traffic_light input”);
2. 在class前使用tag(标签名)
不要使用tag来修饰ID,如下所示:
这样一来,选择器会先遍历所有的div元素,然后匹配#content。(好像jQuery从1.3.1开始改变了选择器核心后,不存在这个问题了。)
3.
将jQuery对象缓存起来
    根据测试,缓存比不缓存,快了2-3倍。
Query(´#top´).find(´p.classA´);改写为:
  1. var cached = jQuery(´#top´);   
  2. cached.find(´p.classA´);
  3. $(‘#parent > .child’) Query内部使用Sizzle引擎,处理各种选择器。Sizzle引擎的选择顺序是从右到左,所以这条语句是先选.child,然后再一个个过滤出父元素#parent,这导致它比最快的形式大约慢70%。
  4. $(‘#parent .child’)

    这条语句与上一条是同样的情况。但是,上一条只选择直接的子元素,这一条可以于选择多级子元素,所以它的速度更慢,大概比最快的形式慢了77%。

永远不要让相同的选择器在你的代码里出现多次.
var $active_light = $('#traffic_light input.on');
$active_light.bind('click', function(){ … })
             .css('border', '1px dashed yellow')
             .css('background-color', 'orange')
             .fadeIn('slow');
  1. $(´div´).find(´h3´).eq(2).html(´Hello´);  

采用链式写法时,jQuery自动缓存每一步的结果,因此比非链式写法要快。根据测试,链式写法比(不使用缓存的)非链式写法,大约快了25%。

4. 对直接的DOM操作进行限制
这里的基本思想是在内存中建立你确实想要的东西,然后更新DOM 。
这并不是一个jQuery最佳实践,但必须进行有效的JavaScript操作 。直接的DOM操作速度很慢。
  例如,你想动态的创建一组列表元素,千万不要这样做,如下所示:
var top_100_list = [...], // 假设这里是100个独一无二的字符串
$mylist = $(”#mylist”); // jQuery 选择到 <ul> 元素
for (var i=0, l=top_100_list.length; i<l; i++){
  $mylist.append(”<li>” + top_100_list[i] + “</li>”);
}
  我们应该将整套元素字符串在插入进dom中之前先全部创建好,如下所示:
var top_100_list = [...],$mylist = $(”#mylist”), top_100_li = “”; // 这个变量将用来存储我们的列表元素
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);
  注:记得以前还看过一朋友写过这样的代码:
for (i = 0; i < 1000; i++) {
    var $myList = $(’#myList’);
    $myList.append(’This is list item ‘ + i);
}
  呵呵,你应该已经看出问题所在了。既然把#mylist循环获取了1000次!

5.冒泡
除非在特殊情况下, 否则每一个js事件(例如:click, mouseover等.)都会冒泡到父级节点。
  当我们需要给多个元素调用同个函数时这点会很有用。
  代替这种效率很差的多元素事件监听的方法就是, 你只需向它们的父节点绑定一次。
  比如, 我们要为一个拥有很多输入框的表单绑定这样的行为: 当输入框被选中时为它添加一个class
  传统的做法是,直接选中input,然后绑定focus等,如下所示:
$(”#entryform input”).bind(”focus”, function(){
    $(this).addClass(”selected”);
}).bind(”blur”, function(){
    $(this).removeClass(”selected”);
});

  当然上面代码能帮我们完成相应的任务,但如果你要寻求更高效的方法,请使用如下代码:

$(”#entryform”).bind(”focus”, function(e){
    var $cell = $(e.target); // e.target 捕捉到触发的目标元素
    $cell.addClass(”selected”);
}).bind(”blur”, function(e){
    var $cell = $(e.target);
    $cell.removeClass(”selected”);
});

  通过在父级监听获取焦点和失去焦点的事件,对目标元素进行操作。
在上面代码中,父级元素扮演了一个调度员的角色, 它可以基于目标元素绑定事件。
  如果你发现你给很多元素绑定了同一个事件监听, 那么现在的你肯定知道哪里做错了。
  同理,在Table操作时,我们也可以使用这种方式加以改进代码:
  普通的方式:

$(’#myTable td’).click(function(){
    $(this).css(’background’, ‘red’);
});

 改进方式:

$(’#myTable’).click(function(e) {
     var $clicked = $(e.target);
     $clicked.css(’background’, ‘red’);
});

  假设有100个td,在使用普通的方式的时候,你绑定了100个事件。
  在改进方式中,你只为一个元素绑定了1个事件,
  至于是100个事件的效率高,还是1个事件的效率高,相信你也能自行分辨了。

6. 推迟到 $(window).load
  jQuery对于开发者来说有一个很诱人的东西, 可以把任何东西挂到$(document).ready下。
  尽管$(document).rady 确实很有用, 它可以在页面渲染时,其它元素还没下载完成就执行。
  如果你发现你的页面一直是载入中的状态,很有可能就是$(document).ready函数引起的。
  你可以通过将jQuery函数绑定到$(window).load 事件的方法来减少页面载入时的cpu使用率。
  它会在所有的html(包括<iframe>)被下载完成后执行。

$(window).load(function(){
    // 页面完全载入后才初始化的jQuery函数.
});

  一些特效的功能,例如拖放, 视觉特效和动画, 预载入隐藏图像等等,都是适合这种技术的场合。
7. 压缩JavaScript
  压缩和最小化你的JavaScript文件。
  在线压缩地址: http://dean.edwards.name/packer/
  压缩之前,请保证你的代码的规范性,否则可能失败,导致Js错误。

8. 尽量使用ID代替Class。
  前面性能优化已经说过,ID选择器的速度是最快的。所以在HTML代码中,能使用ID的尽量使用ID来代替class。
  看下面的一个例子:

// 创建一个list
var $myList = $(’#myList’);
var myListItems = ‘<ul>’;
for (i = 0; i < 1000; i++) {
     myListItems += ‘<li class=”listItem’ + i + ‘”>This is a list item</li>’; //这里使用的是class
 }
myListItems += ‘</ul>’;
$myList.html(myListItems);
// 选择每一个 li
 for (i = 0; i < 1000; i++) {
    var selectedItem = $(’.listItem’ + i);
}

  在代码最后,选择每个li的过程中,总共用了5066毫秒,超过5秒了。
接着我们做一个对比,用ID代替class:

// 创建一个list
var $myList = $(’#myList’);
var myListItems = ‘<ul>’;
for (i = 0; i < 1000; i++) {
    myListItems += ‘<li id=”listItem’ + i + ‘”>This is a list item</li>’; //这里使用的是id
}
myListItems += ‘</ul>’;
$myList.html(myListItems);
 // 选择每一个 li
for (i = 0; i < 1000; i++) {
     var selectedItem = $(’#listItem’ + i);
}

  在上段代码中,选择每个li总共只用了61毫秒,相比class的方式,将近快了100倍。

9. 给选择器一个上下文
  jQuery选择器中有一个这样的选择器,它能指定上下文。

jQuery( expression, context );

  通过它,能缩小选择器在DOM中搜索的范围,达到节省时间,提高效率。
普通方式:

$(’.myDiv’)


  改进方式:

$(’.myDiv’ , $(”#listItem”) )


10. 慎用 .live()方法(应该说尽量不要使用)
  这是jQuery1.3.1版本之后增加的方法,这个方法的功能就是为 新增的DOM元素 动态绑定事件。
  但对于效率来说,这个方法比较占用资源。所以请尽量不要使用它。
  例如有这么一段代码:

<script type=”text/javascript” >
$(function(){
 $(”p”).click(function(){
     alert( $(this).text() );
 });
$(”button”).click(function(){
    $(”<p>this is second p</p>”).appendTo(”body”);
});
}) </script>
<body>
<p>this is first p</p> <button>add</button>
</body>

  运行后,你会发现 新增 的 p元素,并没用被绑定click事件。
  你可以改成.live(”click”)方式解决此问题,代码如下:

$(function(){
$(”p”).live(”click”,function(){ //改成live方式
     alert( $(this).text() );
 });
$(”button”).click(function(){ $(”<p>this is second p</p>”).appendTo(”body”); });})

  但我并不建议大家这么做,我想用另一种方式去解决这个问题,代码如下:

$(function(){
$(”p”).click(function(){
    alert( $(this).text() );
});
$(”button”).click(function(){
    $(”<p>this is second p</p>”).click(function(){  //为新增的元素重新绑定一次
            alert( $(this).text() );
    }).appendTo(”body”);
});
})

  虽然我把绑定事件重新写了一次,代码多了点,但这种方式的效率明显高于live()方式,
  特别是在频繁的DOM操作中,这点非常明显。

11. 子选择器和后代选择器

  后代选择器经常用到,比如:$(”#list  p”);
  后代选择器获取的是元素内部所有元素。
  而有时候实际只要获取 子元素,那么就不应该使用后代选择器。
  应该使用子选择器,代码如下:

$(”#list > p”);


12. 使用data()方法存储临时变量
  下面是一段非常简单的代码,

$(function(){
    var flag = false;
    $(”button”).click(function(){
        if(flag){
            $(”p”).text(”true”);
            flag=false;
        }else{
            $(”p”).text(”false”);
            flag=true;
        }
    });
})

  改用data()方式后,代码如下:

$(function(){
    $(”button”).click(function(){
        if( $(”p”).data(”flag”) ){
            $(”p”).text(”true”);
            $(”p”).data(”flag”,false);
        }else{
             $(”p”).text(”false”);
             $(”p”).data(”flag”,true);
        }
    });
})

13. 不要过度使用jQuery

jQuery速度再快,也无法与原生的javascript方法相比。所以有原生方法可以使用的场合,尽量避免使用jQuery。

请看下面的例子,为a元素绑定一个处理点击事件的函数:

  1. $(´a´).click(function(){   
  2.     alert($(this).attr(´id´));   
  3. });  

这段代码的意思是,点击a元素后,弹出该元素的id属性。为了获取这个属性,必须连续两次调用jQuery,第一次是$(this),第二次是attr(‘id’)。

事实上,这种处理完全不必要。更正确的写法是,直接采用javascript原生方法,调用this.id:

  1. $(´a´).click(function(){   
  2.     alert(this.id);   
  3. });  

根据测试,this.id的速度比$(this).attr(‘id’)快了20多倍。

14. 少改动DOM结构

(1)改动DOM结构开销很大,因此不要频繁使用.append()、.insertBefore()和.insetAfter()这样的方法。

如果要插入多个元素,就先把它们合并,然后再一次性插入。根据测试,合并插入比不合并插入,快了将近10倍。

(2)如果你要对一个DOM元素进行大量处理,应该先用.detach()方法,把这个元素从DOM中取出来,处理完毕以后,再重新插回文档。根据测试,使用.detach()方法比不使用时,快了60%。

(3)如果你要在DOM元素上储存数据,不要写成下面这样:

  1. var elem = $(´#elem´);   
  2. elem.data(key,value);  
而要写成
  1. var elem = $(´#elem´);   
  2. $.data(elem,key,value);  

根据测试,后一种写法要比前一种写法,快了将近10倍。因为elem.data()方法是定义在jQuery函数的prototype对象上面的,而$.data()方法是定义jQuery函数上面的,调用的时候不从复杂的jQuery对象上调用,所以速度快得多。(此处可以参阅下面第10点。)

15. 正确处理循环

循环总是一种比较耗时的操作,如果可以使用复杂的选择器直接选中元素,就不要使用循环,去一个个辨认元素。

javascript原生循环方法for和while,要比jQuery的.each()方法快,应该优先使用原生方法。

16. 尽量少生成jQuery对象

每当你使用一次选择器(比如$(‘#id’)),就会生成一个jQuery对象。jQuery对象是一个很庞大的对象,带有很多属性和方法,会占用不少资源。所以,尽量少生成jQuery对象。

举例来说,许多jQuery方法都有两个版本,一个是供jQuery对象使用的版本,另一个是供jQuery函数使用的版本。下面两个例子,都是取出一个元素的文本,使用的都是text()方法。你既可以使用针对jQuery对象的版本:

  1. var $text = $("#text");   
  2. var $ts = $text.text();  
也可以使用针对jQuery函数的版本:
  1. var $text = $("#text");   
  2. var $ts = $.text($text);  

由于后一种针对jQuery函数的版本不通过jQuery对象操作,所以相对开销较小,速度比较快。



  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值