说明
参考BaritSaiy在cnblog的博客Jquery优化效率 提升性能解决方案而写,主要是对该博文中的表述进行简化,并对各知识点的顺序进行了调整。
该博文主要介绍如何在可以实现相同效果的多种jquery表述语法中选择更为高效的表述。具体包括以下几个方面:
- Dom元素选择器;
- Dom元素操作;
- 事件绑定;
- 页面加载优化;
1.Dom元素选择器优化
jquery中元素选择器中最快的是使用
ID
,其次是使用tag(标签名)
。
ID选择器:$(“#domID”)来自原生的
getElementsById()
,效率最高;标签选择器:$(“div”)来自原生的
getElementsByTagName()
,效率仅次于ID选择器。
基于上面的表述,可以有以下几种优化策略:
1. 尽量使用ID代替Class;
<!-- 使用ID -->
<div id="myDiv"></div>
<!-- 使用Class -->
<div class="myDiv"></div>
2. 能确定tag类型的,在Class前使用标签;
<div class="myDiv"></div>
<div class="myDiv"></div>
<div class="myDiv"></div>
<!--
对于上面的div,使用$("div.myDiv")效率要高于$(".myDiv"),因为前者先用效率较高的getElementsByTagName("div")进行了元素筛选。
因为:
$("div.myDiv")是在所有的div中找className为myDiv的元素;
$(".myDiv")是在所有的元素中找className为myDiv的元素;
-->
3. 给选择器一个上下文;
类似于Class前使用标签来缩小范围,通过为选择器指定上下文,可以减小筛选范围,提高选择器的效率。
语法: jQuery( expression, context );
<div id="wrapper">
<div class="myDiv"></div>
<div class="myDiv"></div>
<div class="myDiv"></div>
</div>
<!--
$('.myDiv' , $("#wrapper"))
或
$('#wrapper .myDiv')
都是不错的选择
-->
2.DOM元素操作
1. 缓存需要重复使用的jquery对象;
对于需要多次操作的jquery对象,应将其缓存成变量,而不是每次使用都时候都用选择器去选取。
//低效:每次使用时都要重新使用选择器筛选,建议不要使用。
function bad(){
$("#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");
}
//较好:将需要重复操作的jquery对象用变量缓存起来,一次筛选,多次操作。
function good(){
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");
}
//改进:在缓存重复操作的jquery对象的同时,使用了链式操作加以改善。
function better(){
var $active_light = $("#traffic_light input.on");
$active_light.bind("click", function(){ ... })
.css("border", "1px dashed yellow")
.css("background-color", "orange")
.fadeIn("slow");
}
2. 缓存全局变量jquery对象;
如果你打算在其他函数中使用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操作进行限制
3. 减少DOM操作次数
直接的Dom操作速度很慢,所以应尽量减少Dom操作的次数。
如果需要批量插入Dom元素,可以选择将它们拼接好后一次性插入。
//低效:每个Dom元素进行一次插入操作,共进行了100次Dom操作;
function bad(){
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元素的字符串拼接好,然后一次性插入,只需1次Dom操作;
function good(){
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);
}
3.事件绑定
简单的说就是:批量绑定相同事件时,绑定到其父元素上(1个事件),而不是在每个子元素上单独绑定一个事件(n个事件)。
除非在特殊情况下, 否则每一个js事件(例如:click, mouseover等。)都会冒泡到父级节点。当我们需要给多个元素调用同个函数时这点会很有用。代替这种效率很差的多元素事件监听的方法就是,你只需向它们的父节点绑定一次。 比如,我们要为一个拥有很多输入框的表单绑定这样的行为:当输入框被选中时为它添加一个class传统的做法是,直接选中input,然后绑定focus等,如下所示:
//Bad:绑定了N个事件
$("#entryform input").bind("focus", function(){
$(this).addClass("selected"); }).bind("blur", function(){
$(this).removeClass("selected");
}
);
//Good:只绑定1个事件
$("#entryform").bind("focus", function(e){
var $cell = $(e.target);
// e.target 捕捉到触发的目标元素
$cell.addClass("selected");
}).bind("blur", function(e){
var $cell = $(e.target);
}
);
4.页面加载优化
1.压缩js文件
压缩和最小化你的JavaScript文件。压缩之前,请保证你的代码的规范性,否则可能失败,导致Js错误。
2.将特效推迟到 $(window).load
jQuery对于开发者来说有一个很诱人的东西,可以把任何东西挂到
$(document).ready
下。尽管$(document).ready
确实很有用, 它可以在页面渲染时,其它元素还没下载完成就执行。如果你发现你的页面一直是载入中的状态,很有可能就是$(document).ready
函数引起的。你可以通过将jQuery函数绑定到$(window).load
事件的方法来减少页面载入时的cpu使用率。它会在所有的html(包括<iframe>
)被下载完成后执行。
$(window).load(function(){
// 页面完全载入后才初始化的jQuery函数.
});
5.其他
1.使用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); } }); });