`
yanzilee9292
  • 浏览: 531283 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

12种jQuery性能优化方法解析

阅读更多

jQuery是目前非常流行的Javascript库之一,随着jQuery应用程序的逐渐增多,其性能优化问题是程序员们不可忽视的,我们知道在 jQuery中最快的选择器是ID选择器,因为它直接来自于JavaScript的getElementById()方法。例如有一段HTML代码:

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

 

<div id="content">
 <form method="post" action="#">
 <h2>交通信号灯</h2>
 <ul id="traffic_light">
 <li><input type="radio" class="on" name="light" value="red" /> 红色</li>
 <li><input type="radio" class="off" name="light" value="yellow" /> 黄色</li>
 <li><input type="radio" class="off" name="light" value="green" /> 绿色</li>
 </ul>
 <input class="button" id="traffic_button" type="submit" value="Go" />
 </form>
</div>
 

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


var traffic_button = $("#content .button");

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


var traffic_button = $("#traffic_button");

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


var traffic_lights = $("#traffic_light input");

2.在class前使用tag(标签名)

在jQuery中第二快的选择器是tag(标签)选择器( 比如:$("head") )。跟ID选择器累时,因为它来自原生的getElementsByTagName()方法。继续看刚才那段HTML代码:

<div id="content">
 <form method="post" action="#">
 <h2>交通信号灯</h2>
 <ul id="traffic_light">
 <li><input type="radio" class="on" name="light" value="red" /> 红色</li>
 <li><input type="radio" class="off" name="light" value="yellow" /> 黄色</li>
 <li><input type="radio" class="off" name="light" value="green" /> 绿色</li>
 </ul>
 <input class="button" id="traffic_button" type="submit" value="Go" />
 </form>
</div>
 

比如需要选择红绿单选框,那么可以使用一个tag name来限制(修饰)class ,如下所示:


 var active_light = $("input.on");
 

当然也可以结合 就近的ID,如下所示:


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

在使用tag来修饰class的时候,我们需要注意以下几点:

(1)不要使用tag来修饰ID,如下所示:

 var content = $("div#content");
 

这样一来,选择器会先遍历所有的div元素,然后匹配#content。

(2)不要画蛇添足的使用ID来修饰ID,如下所示:

 var traffic_light = $("#content #traffic_light");
 

3.将jQuery对象缓存起来

把jQuery对象缓存起来就是要告诉我们 要养成将jQuery对象缓存进变量的习惯。下面是一个jQuery新手写的一段代码:


$("#traffic_light input.on").bind("click", function(){ ... });
$("#traffic_light input.on").css("border", "1px dashed yellow");
$("#traffic_light input.on").css("background-color", "orange");
$("#traffic_light input.on").fadeIn("slow");

 

 

但切记不要这么做。我们应该先将对象缓存进一个变量然后再操作,如下所示:


var $active_light = $("#traffic_light input.on");
$active_light.bind("click", function(){ ... });
$active_light.css("border", "1px dashed yellow");
$active_light.css("background-color", "orange"); $active_light.fadeIn("slow");

 

 

记住,永远不要让相同的选择器在你的代码里出现多次:

(1)为了区分普通的JavaScript对象和jQuery对象,可以在变量首字母前加上$符号。
(2)上面代码可以使用jQuery的链式操作加以改善。如下所示:


var $active_light = $("#traffic_light input.on");
$active_light.bind("click", function(){ ... })
.css("border", "1px dashed yellow")
.css("background-color", "orange")
.fadeIn("slow");

 

 

如果你打算在其他函数中使用jQuery对象,那么你必须把它们缓存到全局环境中。如下代码所示:


 // 在全局范围定义一个对象 (例如: window对象)
 window.$my = {
 head : $("head"),
 traffic_light : $("#traffic_light"),
 traffic_button : $("#traffic_button")
 };
 function do_something(){
 // 现在你可以引用存储的结果并操作它们
 var script = document.createElement("script");
 $my.head.append(script);
 // 当你在函数内部操作是, 可以继续将查询存入全局对象中去.
 $my.cool_results = $("#some_ul li");
 $my.other_results = $("#some_table td");
 // 将全局函数作为一个普通的jquery对象去使用.
 $my.other_results.css("border-color", "red");
 $my.traffic_light.css("border-color", "green");
 }
 //你也可以在其他函数中 使用它

 

 

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);
 }

 

 

你应该已经看出问题所在了。

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操作时,我们也可以使用这种方式加以改进代码:普通的方式:


1. $('#myTable td').click(function(){
2. $(this).css('background', 'red');
3. });
4. 改进方式:
5. $('#myTable').click(function(e) {
6. var $clicked = $(e.target);
7. $clicked.css('background', 'red');
8. });

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

6.推迟到 $(window).load

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


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

一些特效的功能,例如拖放, 视觉特效和动画, 预载入隐藏图像等等,都是适合这种技术的场合。

7.压缩JavaScript

压缩和最小化你的JavaScript文件。压缩之前,请保证你的代码的规范性,否则可能失败,导致Js错误。

8.尽量使用ID代替Class

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


1. // 创建一个list
2. var $myList = $('#myList');
3. var myListItems = '<ul>';
4. for (i = 0; i < 1000; i++) {
5. myListItems += '<li class="listItem' + i + '">This is a list item</li>'; //这里使用的是class
6. }
7. myListItems += '</ul>';
8. $myList.html(myListItems);
9. // 选择每一个 li
10. for (i = 0; i < 1000; i++) {
11. var selectedItem = $('.listItem' + i);
12. }

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


1. // 创建一个list
2. var $myList = $('#myList');
3. var myListItems = '<ul>';
4. for (i = 0; i < 1000; i++) {
5. myListItems += '<li id="listItem' + i + '">This is a list item</li>'; //这里使用的是id
6. }
7. myListItems += '</ul>';
8. $myList.html(myListItems);
9. // 选择每一个 li
10. for (i = 0; i < 1000; i++) {
11. var selectedItem = $('#listItem' + i);
12. }

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

9.给选择器一个上下文

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


1. jQuery( expression, context );

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

普通方式:


1. $('.myDiv')

改进方式:

1. $('.myDiv' , $("#listItem") )

10.慎用 .live()方法(应该说尽量不要使用)

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


1. <script type="text/javascript" >
2. $(function(){
3. $("p").click(function(){
4. alert( $(this).text() );
5. });
6. $("button").click(function(){
7. $("<p>this is second p</p>").appendTo("body");
8. });
9. }) </script>
10. <body>
11. <p>this is first p</p> <button>add</button>
12. </body>

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


1. $(function(){
2. $("p").live("click",function(){ //改成live方式
3. alert( $(this).text() );
4. });
5. $("button").click(function(){ $("<p>this is second p</p>").appendTo("body"); });})

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


1. $(function(){
2. $("p").click(function(){
3. alert( $(this).text() );
4. });
5. $("button").click(function(){
6. $("<p>this is second p</p>").click(function(){ //为新增的元素重新绑定一次
7. alert( $(this).text() );
8. }).appendTo("body");
9. });
10. })

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

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

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


1. $("#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);
   }
 });
})
 

 

分享到:
评论

相关推荐

    锋利的jQuery(第2版).单东林、张晓菲、魏然(带详细书签)

    《锋利的jQuery(第2版)》循序渐进地对jQuery的各种函数和方法调用进行了介绍,读者可以系统地掌握jQuery的选择器、DOM操作、事件和动画、AJAX应用、插件、jQuery Mobile、jQuery各个版本变化、jQuery性能优化和技巧...

    jQuery EasyUI 1.4.5 优化性能版

    此版本修正了1.4.4中datagrid、treegrid、tree组件出现的问题,改进了window、...综合1.4.X版本开发时遇到的性能瓶颈,整合到1.4.5中,在庞大的DOM结构下,有效提升IE浏览器解析EasyUI的速度!!值得大家收藏、使用。

    jQuery EasyUI 1.4.5 优化性能版(已测试)

    此版本修正了1.4.4中datagrid、treegrid、tree组件出现的...综合1.4.X版本开发时遇到的性能瓶颈,整合到1.4.5中,在庞大的DOM结构下,有效提升各浏览器(特别是IE旧版浏览器)解析EasyUI的速度!!值得大家收藏、使用。

    超实用的jQuery代码段

    超实用的jQuery代码段精选近350个jQuery代码段,涵盖页面开发中绝大多数要点、技巧与方法,堪称史上最实用的jQuery代码参考书,可以视为网页设计与网站建设人员的好帮手。《超实用的jQuery代码段》的代码跨平台、跨...

    jquery.validation.optimised:jQuery 验证,对具有大量输入的页面进行性能优化

    jquery.validation.optimised jQuery 验证,对具有大量输入的页面进行性能优化对于具有大量输入(通常 &gt; 100)的页面,jquery validate 在解析所有元素时非常慢,在表单提交时创建 UI 挂起。 此版本包含优化的解析和...

    jquery-easyui-EDT-1.5.5.7z

    panel:优化调整尺寸时的组件重绘的性能问题; filebox:'files'方法允许用户获取选择的文件列表; searchbox:优化'selectName'方法。 jQuery EasyUI 1.5.3 版本更新内容 Bug(修复) combobox:修复在标签中初始...

    jquery-csv:jQuery CSV解析器插件。 经过战斗考验| 优化| 100%IETF RFC 4180完成

    这是一个完整的,可定制的,经过战斗测试,性能优化的CSV分析器,它遵循传统的jQuery样式的语法。 具有超薄的Chomsky-Type III解析器实现。 完全(即100%)符合 。 包括一些规范无法涵盖的边缘情况的涵盖范围。 ...

    jquery-csv:自动从code.google.compjquery-csv导出

    寻找一个完整的,端到端,经过测试的,性能优化的CSV解析器,该解析器以熟悉的jQuery语法样式提供吗? 欢迎... 该库是另一种动物,具有细长的Chomsky-Type III解析器实现。 完全(即100%)符合IETF RFC 4180。 ...

    庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术

    6.9 页面状态性能优化策略 238 6.9.1 存储位置优化——把视图状态信息保存在服务端而非客户端 238 6.9.2 体积优化——压缩视图状态数据 240 6.9.3 分块存储视图状态数据 243 6.10 视图状态和控件状态的总结 243 ...

    庖丁解牛 纵向切入ASP.NET 3.5控件和组件开发 part1

    6.9 页面状态性能优化策略 238 6.9.1 存储位置优化——把视图状态信息保存在服务端而非客户端 238 6.9.2 体积优化——压缩视图状态数据 240 6.9.3 分块存储视图状态数据 243 6.10 视图状态和控件状态的总结 243 ...

    庖丁解牛 纵向切入ASP.NET 3.5控件和组件开发 part2

    6.9 页面状态性能优化策略 238 6.9.1 存储位置优化——把视图状态信息保存在服务端而非客户端 238 6.9.2 体积优化——压缩视图状态数据 240 6.9.3 分块存储视图状态数据 243 6.10 视图状态和控件状态的总结 243 ...

    ASP.NET MVC 3高级编程

    11.2 依赖解析器的用法 272 11.2.1 单一注册服务 274 11.2.2 复合注册服务 275 11.2.3 创建任意对象 278 11.3 小结 280 第12章 单元测试 281 12.1 单元测试和测试驱动开发的意义 282 12.1.1 单元测试的定义 ...

    王凯某求职简历_20201129154431_嵌入式_java简历_程序员简历模板_计算机相关专业.doc

    12. Excel文件操作:熟悉POI技术进行Excel文件的上传解析和下载写入操作。 13. 前端框架:熟悉Bootstrap前端框架,实现良好的页面交互效果。 14. 权限管理框架:熟悉Shiro框架,方面不同角色对项目的操作。 15. ...

    php面试题_百度.doc

    可以使用 JavaScript 的 XMLHttpRequest 对象或 jQuery 库来实现 Ajax 请求。例如: ```javascript var xhr = new XMLHttpRequest(); xhr.open('GET', 'data.json', true); xhr.onload = function() { if (xhr....

    梁某某-3年Java-本科_嵌入式_java简历_程序员简历模板_计算机相关专业.doc

    1. Oracle数据库基础知识:掌握Oracle数据库的基础概念和应用,包括SQL语句、数据库设计、性能优化等。 2. MySQL数据库基础知识:熟悉MySQL数据库的基础概念和应用,包括SQL语句、数据库设计、性能优化等。 3. Redis...

    pinghsu:Pinghsu,Typecho主题

    Pinghsu是一种以前端性能优化为出发点而制作的Typecho主题,同时又兼顾设计美学和视觉传达。主题命名取自作者姓名和其女朋友姓名的最后一个字的港式英文,挣扎于Hsuping还是Pinghsu ,最后取为Pinghsu,意为一切都是...

    java面试题

    51.5. java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 25 52. 数据连接池 25 52.1. 连接池的基本原理: 25 52.2. 连接池的工作机制 25 52.3. 建立连接池 26 ...

    js简单课程设计

    js简单应用的课程设计,主要运用多种简单js,知识点:JavaScript+jQuery+Ajax+正则表达式+面向对象+js插件+代码性能优化+github+seaJs+requireJs+gulp 通过学习JavaScript基础变量、运算符、数据类型,函数,DOM...

    千方百计笔试题大全

    70、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 17 71、启动一个线程是用run()还是start()? 17 72、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 18 73...

    java面试宝典

    70、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 17 71、启动一个线程是用run()还是start()? 17 72、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 18 73...

Global site tag (gtag.js) - Google Analytics