jQuery框架常用的性能优化

时间:2021-08-14 20:02:31

jQuery作为一个JavaScript非常优秀的库
是我们在学习前端过程中必学的
虽然它的流行程度已经没有那么巅峰了
但是学习了它对我们学习理解其他库以及框架来说很有帮助
今天第一次写jQuery的相关文章,就先把这个性能问题拿出来
因为大家把时间都用在jQuery语法上了,对这个库的性能优化不是很了解
下面我来给大家总结一下jQuery常用的性能优化


1.选择器使用

jQuery提供了很多方便的选择器语法,介绍几个常用的及它们的性能排名

  1. id选择器 $(‘#id’)
    毫无疑问是最佳性能,因为它底层就直接使用了document.getElementById()
    所以提高性能可以从有id的元素往下查找,从而缩小查找范围,e.g. $(‘#wrapper’).find(‘div’);
  2. 标签选择器 $(‘tag’)
    同样性能不错,底层直接调用document.getElementByTagName() ,同样因为浏览器兼容性好
  3. class选择器 $(‘.class’)
    之所以它性能没有id和标签选择器好,就是应为让人头疼的IE8及低版本没有,没有的话就只能靠DOM搜索
  4. 属性选择器 $(‘[attribute=value]’)
    这个现代浏览器使用querySelectorAll(),旧的就得使用DOM搜索来达到目的了,性能不理想
  5. 伪选择器 $(‘:animated’)
    我们经常使用的伪选择器其实性能并不好,jQuery需要搜索每一个元素来定位,一定要斟酌使用
    使用的话最好缩小范围 e.g.$(‘wrapper’).find/filter(‘:animated’)

    综上,

    • 尽量使用ID、标签选择器(class选择器前叠加标签选择器)
    • 尽量为选择器指定上下文

2.缓存jq对象

缓存思想对于提高性能的重要性那是不言而喻的
我在循环语句的性能问题容中也提到了这种思想
看看你的代码中有没有类似这样的写法

//待改进
$('#wrapper div.demo').css('background-color','red');
$('#wrapper div.demo').animate('top','100px');
$('#wrapper div.demo').on('click',function(){...});
......

这样做的结果是,每行都要创建一个一模一样的jQuery对象,并且每次都要去查找DOM
所以我们可以最好这样做

//待改进
$demo = $('#wrapper div.demo');
$demo.css('background-color','red');
$demo.animate('top','100px');
$demo.on('click',function(){...});
......

把对象都缓存到一个变量里,这样避免了它多次查找DOM,避免多次创建对象
而且看起来也清爽了许多不是么
变量前加“$”符号代表它是一个jQuery对象,用以区别普通变量
如果你想在其它函数中使用jQuery对象,那么我们可以缓存到全局,像这样

window.$my = {
head: $('#head'),
content: $('#content'),
footer: $('#footer'),
...
}
function foo(){
$my.head.css(...);
}

只要记住一点就好了
不要在你的代码里出现重复的选择器

3.链式调用

链式调用算是jQuery的特点了
仅仅是简单的在函数中返回了这个对象,便实现了像一条链子的调用方式
我特意在上面的代码中同样标注了“待改进”就是怕大家把它刻在心里……[]~( ̄▽ ̄)~*
我们来修改一下代码

$demo = $('#wrapper div.demo');
$demo.css('background-color','red')
.animate('top','100px')
.on('click',function(){...});

或者如果你以后都不会用到这个选择器,干脆

$('#wrapper div.demo').css('background-color','red')
.animate('top','100px')
.on('click',function(){...});

不缓存也可以
毫无疑问使用jQuery的链式调用可以有效提高性能
而且这样更简洁、更优雅……

4.循环DOM操作

虽然很多jQuery方法很方便,但是方便的同时会带来性能问题,一定要慎重使用
循环和DOM操作都是影响性能的关键
更不要在循环中获取jq对象
这里有个小问题要注意

var $list = $('ul.list');
for(var i = 0, i < 100; i++){
$list.append('<li>' + ... + '</li>');
}

这样直接在每次迭代中插入DOM节点,十分耗性能
我们可以这样做

var $list = $('ul.list');
var temp = '';
for(var i = 0; i < 100; i++){
temp += '<li>' + ... + '</li>';
}
$list.html(temp);

5.精简代码

简化代码确实可以提高性能
比如像这样的代码

$demo.css('width','100px');
.css('height','100px');
.css('color','red');

这样太麻烦了,可以改写(只是举个例子,倒是没人这样写)

$demo.css({
'width': '100px',
'height': '100px',
'color': 'red'
});

6.拼接字符串

使用join()来拼接字符串而不是用“+”
这个提升性能的小技巧不局限于jQuery
在原生js中我们也应该注意

var arr = [];
for(var i = 0; i < 100; i++){
arr[i] = '<div class="demo' + i + '">'
}

('.wrapper').html(arr.join());

join()能够优化性能

7.使用原生js

并不是说让大家都使用原生js
那这个jquery类库就没意义了
我的意思是说如果使用原生js同样可以很简单的解决问题,那么就使用原生js吧
这可以提高性能
然我想起了一句广告词“劲酒虽好,可我要贪杯哦”(感觉好奇怪)
jQuery虽然好,但使用要适度
比如$.each有时候换成for循环也许会更好
再比如$(this).css(‘color’,’red’) 换成 this.style.color = ‘red’
还有很多,如果兼容问题并不是很了解,还是建议使用jQuery提供的方法
毕竟在这方面jQuery处理的很棒

8.事件委托

JavaScript中的事件都会冒泡到父级
所以假如ul下面有1亿个li(虽然不可能)
那么就把事件绑定在ul上吧,然后判断触发事件的源对象
在jQuery中,我们使用on来实现

$('ul').on('click','li',function(){
......
});

性能肯定要比

$('li').on('click',function(){
.......
});

强很多

假如真有一亿个li,那你也只能使用事件委托/事件代理了
这个事件委托的优势不仅仅是这样
如果你在ul的下面新添加li,它同样会冒泡给父级,由父级代理处理
这样避免了修改或添加代码,增加绑定事件

9.直接函数

我们应该使用底层的直接函数
这个问题很好理解
比如我们应该使用 .ajax(), .get(), .post() .ajax()

10.扩展插件

如果你的代码需要被多次调用,
建议大家把代码创建为插件
jQuery中扩展插件的方法有两种
$.extend() 封装全局函数的插件(还可以扩展自定义插件但不怎么用)
$.fn.extend() 封装对象方法的插件
这个扩展插件日后我会写一个专题

11.库更新

最后一点就很简单了
jQuery版本的更新便会优化性能、修复bug或者增加方法
同时也可能删除一些不常用的方法,毕竟不是完全向后兼容的

总结

  • 尽量使用ID、标签选择器
  • 尽量为选择器指定上下文/使用find()
  • 避免出现重复选择器,缓存jq对象
  • 链式调用
  • 避免循环内获取jq对象
  • 尽量避免循环中DOM操作
  • 尽量减少对HTML结构的修改
  • 注意精简代码
  • 使用join()拼接字符串
  • 需要的时候使用原生JavaScript
  • 使用on()事件委托
  • 扩展插件,提高重用性
  • 注意更新库版本

==主页传送门==