jQuery代码性能优化的10种方法


Posted in Javascript onJune 21, 2016

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

在jQuery中最快的选择器是ID选择器 ($('#someid')). 这是因为它直接映射为JavaScript的getElementById()方法。
选择单个元素

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

选择多个元素

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

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

2、在Classes前面使用Tags

在jQuery中第二快的选择器就是Tag选择器 ($('head')). 而这是因为它直接映射到JavaScript的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>

总是在一个Class前面加上一个tag名字(记得从一个ID传下来)

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

注意:在jQuery里Class选择器是最慢的一个选择器;在IE中它循环整个DOM。可能的话尽量避免使用它。不要在ID前面 加Tags。例如,它会因为去循环所有的<div>元素去寻找ID为content的<div>,而导致很慢。

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

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

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

3、缓存jQuery对象

养成保存jQuery对象到一个变量上(就像上面的例子)的习惯。例如,不要这样做:

$('#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');

取而代之,首现保存jQuery变量到一个本地变量后,再继续你的操作。

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

提示:使用$前辍表示我们的本地变量是一个jQuery包集。记住,不要在你的应该程序里出现一次以上的jQuery重复的选择操作。 额外提示:延迟存储jQuery对象结果。

如果你想在你的程序的其它地方使用jQuery结果对象(result object(s)),或者你的函数要执行多次,要把它缓存在一个全局范围的对象里。通过定义一个全局容器保存jQuery结果对象,就可以在其它的函数里引用它。

// 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允许我们在一个包集上附加其它的选择器。因为我们已经在本地变量里保存了父对象这样会减少以后在选择器上的性能开销。

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

提示:可以用逗号隔开一次定义多个本地变量,这样可以节省一些字节。

6、限制直接对DOM操作

DOM操作的基本做法是在内存中创建DOM结构,然后再更新DOM结构。这不是jQuery最好的做法,但对JavaScript来讲是高效的。直接操作DOM结构性能是低下的。 例如,如果你需要动态创建一列元素,不要这样做:

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结构之前先在一个字符串里创建一套元素。
代码

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结构之前我们应该总是在一个父节点里包含许多元素

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

如是你照着上面的做了还是对性能有些迷惑的话,可以参考以下内容:

* 试一下jQuery提供的Clone()方法。Clone()方法创建节点数的拷贝,随后你可以在这个副本中进行操作。

* 使用DOM DocumentFragments. As the creator of jQuery points out, 比直接操作DOM性能上更好. 先创建你需要的结构(就像我们上面用一个字符串做的一样), 然后使用jQuery的 insert or replace methods.

7、事件委托(又名:冒泡事件)

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

$('#myList li).bind('click', function(){

 $(this).addClass('clicked'); // do stuff

});

反而,我们应该在父级侦听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

 }

});

父节点担当着发报机的工作,可以在触发了事件的目标element上做一些工作。如果你发现自己把一个event listener帮定到很多个element上,那么你这种做法是不正确的。

8、消除查询浪费

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

<script type="text/javascript>mylib.article.init();</script></body& gt;如果你的页面模板包含多种有可能在页面或者不在页面上的模块,或者为了可视化效果你需要它们稍后再初如化,你应该在这些模块之后立即放置初如化函数。

<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库看起来应该是这样的:

var mylib ={

 article_page : {

  init : function()  {

   // Article page specific jQuery functions. 

  }

 }, 

 traffic_light : {

  init : function()  {

   // Traffic light specific jQuery functions. 

  }

 }

}

9、遵从$(windows).load

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

$(window).load(function(){

 // jQuery functions to initialize after the page has loaded.

});

多余的功能,如拖拽、帮定可视化效果和动画、预读取图片等,使用这种方法比较好。

10、压缩JS

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

学习和最有效的使用jQuery,最好的方法就是去查jQuery的文档和手册了。

以上就是本文的全部内容,了解更多jQuery的语法,大家可以查看:《jQuery 1.10.3 在线手册》,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 简单高效判断数据类型 系列函数 By shawl.qiu
Mar 06 Javascript
JavaScript获取页面上某个元素的代码
Mar 13 Javascript
调用jQuery滑出效果时闪烁的解决方法
Mar 27 Javascript
js星星评分效果
Jul 24 Javascript
jquery判断复选框是否选中进行答题提示特效
Dec 10 Javascript
JavaScript使用Range调色及透明度实例
Sep 25 Javascript
通过扫描二维码打开app的实现代码
Nov 10 Javascript
微信小程序实现tab页面切换功能
Jul 13 Javascript
详解React中传入组件的props改变时更新组件的几种实现方法
Sep 13 Javascript
iSlider手机端图片滑动切换插件使用详解
Dec 24 Javascript
JS替换字符串中指定位置的字符(多种方法)
May 28 Javascript
如何利用React实现图片识别App
Feb 18 Javascript
JS实现兼容各种浏览器的获取选择文本的方法【测试可用】
Jun 21 #Javascript
JS实现兼容各种浏览器的高级拖动方法完整实例【测试可用】
Jun 21 #Javascript
JavaScript检测原始值、引用值、属性
Jun 20 #Javascript
Js 获取当前函数参数对象的实现代码
Jun 20 #Javascript
JS实现鼠标框选效果完整实例
Jun 20 #Javascript
javascript事件冒泡简单示例
Jun 20 #Javascript
JS实现的打字机效果完整实例
Jun 20 #Javascript
You might like
php获取后台Job管理的实现代码
2011/06/10 PHP
PHP实现算式验证码和汉字验证码实例
2015/03/09 PHP
Yii2处理密码加密及验证的方法
2019/05/12 PHP
javascript中如何处理引号编码&amp;#034;
2013/08/15 Javascript
jquery ajax对特殊字符进行转义防止js注入使用示例
2013/11/21 Javascript
jquery弹窗插件colorbox绑定动态生成元素的方法
2014/06/20 Javascript
javascript trim函数在IE下不能用的解决方法
2014/09/12 Javascript
cookie的secure属性详解
2015/04/08 Javascript
vue.js中$watch的用法示例
2016/10/04 Javascript
简单实现js点击展开二级菜单功能
2017/05/16 Javascript
Angular搜索 过滤 批量删除 添加 表单验证功能集锦(实例代码)
2017/10/25 Javascript
jQuery 实现左右两侧菜单添加、移除功能
2018/01/02 jQuery
JS删除数组里的某个元素方法
2018/02/03 Javascript
Vue使用axios出现options请求方法
2019/05/30 Javascript
基于vue-cli搭建多模块且各模块独立打包的项目
2019/06/12 Javascript
解决iview table组件里的 固定列 表格不自适应的问题
2020/11/13 Javascript
[53:52]OG vs EG 2018国际邀请赛淘汰赛BO3 第二场 8.23
2018/08/24 DOTA
跟老齐学Python之print详解
2014/09/28 Python
简单说明Python中的装饰器的用法
2015/04/24 Python
numpy中实现ndarray数组返回符合特定条件的索引方法
2018/04/17 Python
Python WSGI的深入理解
2018/08/01 Python
Python OrderedDict的使用案例解析
2019/10/25 Python
python Shapely使用指南详解
2020/02/18 Python
基于Numba提高python运行效率过程解析
2020/03/02 Python
jupyter修改文件名方式(TensorFlow)
2020/04/21 Python
Python数据可视化实现漏斗图过程图解
2020/07/20 Python
Python爬虫抓取指定网页图片代码实例
2020/07/24 Python
Python创建临时文件和文件夹
2020/08/05 Python
华润集团网上药店:健一网
2016/09/19 全球购物
阿联酋彩妆品牌:OUD MILANO
2019/10/06 全球购物
出国留学担保书
2014/05/20 职场文书
学习教师法的心得体会
2014/09/03 职场文书
2015年学校总务工作总结
2015/07/20 职场文书
go语言中切片与内存复制 memcpy 的实现操作
2021/04/27 Golang
关于MybatisPlus配置双数据库驱动连接数据库问题
2022/01/22 Java/Android
Android移动应用开发指南之六种布局详解
2022/09/23 Java/Android