jquery优化
个人整理,不定期更新……
一、合理使用选择器
1.最快的选择器:id选择器和元素标签选择器
在我们讨论选择多个元素的时候,我们真正需要知道的是DOM的遍历和循环才是性能低下的原因。为了尽量减少性能损失, 总是使用最近的父id去寻找。
在jQuery中最快的选择器是ID选择器,因为它直接来自于JavaScript的getElementById()方法。
在jQuery中第二快的选择器就是Tag选择器,而这是因为它直接映射到JavaScript的getElementsByTagName()方法。
2.较慢的选择器:class选择器
在jQuery里Class选择器是较慢的一个选择器。Firefox、Safari、Chrome、Opera浏览器,都有原生方法getElementByClassName(),所以速度并不慢。但是,IE5-IE8都没有部署这个方法,所以这个选择器在IE中会相当慢。
用id或者tag来修饰class。
3.最慢的选择器:伪类选择器和属性选择器
先来看例子。找出网页中所有的隐藏元素,就要用到伪类选择器:$(':hidden')
属性选择器的例子则是:$('[attribute=value]')
这两种语句是最慢的,因为浏览器没有针对它们的原生方法。但是,一些浏览器的新版本,增加了querySelector()和querySelectorAll()方法,因此会使这类选择器的性能有大幅提高。
小节:不要过度使用jQuery。jQuery速度再快,也无法与原生的javascript方法相比。所以有原生方法可以使用的场合,尽量避免使用jQuery。以最简单的选择器为例,document.getElementById("foo")要比$("#foo")快10多倍。
二、做好缓存
通过定义一个全局容器保存jQuery结果对象,不要让相同的选择器在你的代码里出现多次。
为了区分普通的JavaScript对象和jQuery对象,可以在变量首字母前加上 $ 符号。
可以使用jQuery的链式操作加以改善,还可以使用子查询。
三、少改动DOM结构
1.改动DOM结构开销很大,因此不要频繁使用.append()、.insertBefore()和.insetAfter()这样的方法。
如果要插入多个元素,就先把它们合并,然后再一次性插入。根据测试,合并插入比不合并插入,快了将近10倍。
2.如果你要对一个DOM元素进行大量处理,应该先用.detach()方法,把这个元素从DOM中取出来,处理完毕以后,再重新插回文档。根据测试,使用.detach()方法比不使用时,快了60%。
四、尽量少生成jQuery对象
每当你使用一次选择器(比如$('#id')),就会生成一个jQuery对象。jQuery对象是一个很庞大的对象,带有很多属性和方法,会占用不少资源。所以,尽量少生成jQuery对象。
举例来说,许多jQuery方法都有两个版本,一个是供jQuery对象使用的版本,另一个是供jQuery函数使用的版本。下面两个例子,都是取出一个元素的文本,使用的都是text()方法。
你既可以使用针对jQuery对象的版本:
var elem = $('#elem');
elem.data(key,value);
也可以使用针对jQuery函数的版本:
var elem = $('#elem');
$.data(elem[0],key,value);
根据测试,后一种写法要比前一种写法,快了将近10倍。因为elem.data()方法是定义在jQuery函数的prototype对象上面的,而$.data()方法是定义jQuery函数上面的,调用的时候不从复杂的jQuery对象上调用,所以速度快得多。
五、选择作用域链最短的方法
严格地说,这一条原则对所有Javascript编程都适用,而不仅仅针对jQuery。
我们知道,Javascript的变量采用链式作用域。读取变量的时候,先在当前作用域寻找该变量,如果找不到,就前往上一层的作用域寻找该变量。这样的设计,使得读取局部变量比读取全局变量快得多。
六、事件委托(又名:冒泡事件)
除非特别说明,每一个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上做一些工作。