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 相关文章推荐
JS window.opener返回父页面的应用
Oct 24 Javascript
web网页按比例显示图片实现原理及js代码
Aug 09 Javascript
node.js 和HTML5开发本地桌面应用程序
Dec 13 Javascript
通过AngularJS实现图片上传及缩略图展示示例
Jan 03 Javascript
jQuery实现的点击标题文字切换字体效果示例【测试可用】
Apr 26 jQuery
JavaScript常见JSON操作实例分析
Aug 08 Javascript
react build 后打包发布总结
Aug 24 Javascript
代码分析vue中如何配置less
Sep 28 Javascript
在Create React App中启用Sass和Less的方法示例
Jan 16 Javascript
详解从0开始搭建微信小程序(前后端)的全过程
Apr 15 Javascript
Vue程序调试的方法
Jun 17 Javascript
Layer.js实现表格溢出内容省略号显示,悬停显示全部的方法
Sep 16 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
浅析linux下apache服务器的配置和管理
2013/08/10 PHP
PHP实现今天是星期几的几种写法
2013/09/26 PHP
讲解WordPress开发中一些常用的debug技巧
2015/12/18 PHP
JS控制一个DIV层在指定时间内消失的方法
2014/02/17 Javascript
javascript初学者常用技巧
2014/09/02 Javascript
javascript中setAttribute()函数使用方法及兼容性
2015/07/19 Javascript
Jquery为DIV添加click事件的简单实例
2016/06/02 Javascript
JS实现兼容各种浏览器的高级拖动方法完整实例【测试可用】
2016/06/21 Javascript
微信小程序 定义全局数据、函数复用、模版等详细介绍
2016/10/27 Javascript
不使用script导入js文件的几种方法
2016/10/27 Javascript
html5 canvas 详细使用教程
2017/01/20 Javascript
javascript表达式和运算符详解
2017/02/07 Javascript
从零开始学习Node.js系列教程之设置HTTP头的方法示例
2017/04/13 Javascript
vue自动化表单实例分析
2018/05/06 Javascript
Vue中UI组件库之Vuex与虚拟服务器初识
2019/05/07 Javascript
layui之数据表格--与后台交互获取数据的方法
2019/09/29 Javascript
vue3 watch和watchEffect的使用以及有哪些区别
2021/01/26 Vue.js
[11:01]2014DOTA2西雅图邀请赛 冷冷带你探秘威斯汀
2014/07/08 DOTA
深入浅析Python中的yield关键字
2018/01/24 Python
Python 脚本获取ES 存储容量的实例
2018/12/27 Python
Python3实现的回文数判断及罗马数字转整数算法示例
2019/03/27 Python
Python3.5面向对象程序设计之类的继承和多态详解
2019/04/24 Python
python挖矿算力测试程序详解
2019/07/03 Python
使用Python为中秋节绘制一块美味的月饼
2019/09/11 Python
Python日志logging模块功能与用法详解
2020/04/09 Python
torchxrayvision包安装过程(附pytorch1.6cpu版安装)
2020/08/26 Python
PyCharm中关于安装第三方包的三个建议
2020/09/17 Python
Flask-SocketIO服务端安装及使用代码示例
2020/11/26 Python
Python虚拟环境virtualenv创建及使用过程图解
2020/12/08 Python
Shell编程面试题
2012/05/30 面试题
教师节促销活动方案
2014/02/14 职场文书
宣传部部长竞选演讲稿
2014/04/26 职场文书
公司员工离职证明书
2014/10/04 职场文书
2019最新版试用期劳动合同模板!
2019/07/04 职场文书
golang如何去除多余空白字符(含制表符)
2021/04/25 Golang
MySQL数据库如何使用Shell进行连接
2022/04/12 MySQL