js性能优化与调试技巧
尽早加载关键的JavaScript资源
可以将关键js资源放在标签中,但是这个方法不推荐,会阻塞渲染
<head>
...
<script src="main.js"></script>
...
</head>
可以使用预加载
<head>
...
<!-- 预加载js文件 -->
<link rel="preload" href="important-js.js" as="script" />
<!-- 预加载js模块 -->
<link rel="modulepreload" href="important-module.js" />
...
</head>
减少重绘和重排
重绘是页面元素外观发生改变,但是页面排版没有发生变化,比如改变一些样式,颜色和边框
重排是元素的尺寸、位置或者显示状态发生变化,导致布局发生变化,存在状态发生变化,将会改变布局,浏览器重新计算元素的几何属性,然后重新排布页面元素,例如:页面元素的宽高,使用display:none控制元素显示隐藏,边距发生改变
重绘不一定会导致重排,重排一定会导致重绘。
可以根据下面的几种方法减少重绘重排:
- 使用节流和防抖技术
- 避免频繁改变元素的样式属性,和布局属性
- 减少使用表格,因为其中一个元素发生改变,就会导致整个表格发生改变
- 尽量使用opcitaty,transform等不影响页面布局的属性实现动画效果,而不使用height,width,left,top等影响页面布局的属性
- 尽量使用绝对定位来实现动画效果,因为不会影响其他元素的布局
- 避免使用JS一个样式修改完接着改下一个样式,最好一次性更改CSS样式,或者将样式列表定义为class的名称
- 尽量在DOM的末端修改样式
节流
节流:
- 点击后,判断与上一次事件的间隔时间,如果大于规定时间则执行
- 适用于:页面滑动,搜索事件
//调用
const debouncedFunc=a(fn,100)
debouncedFunc(1,2,3)//代表args这里捕获的参数是[1,2,3]
function a(fn,wait){
let timer=null
return function(...args){
let content=this
if(timer){
clearTimeout(timer)
}
timer=setTimeout(function(){
fn.apply(content,args)
},wait)
}
}
a函数接收两个参数:fn是需要执行的函数,wait是延迟的时间。- 每次触发事件时,先清除上一次的
timer,然后重新设置一个新的定时器。 - 只有在指定的
wait时间内没有新的事件触发时,fn才会被执行。
防抖
防抖:
- 多次点击之后执行最后一次事件(设置成一个定时函数执行)
- 适用于:键盘监听的搜索框(翻译),表单验证,监听窗口
function b(fn,wait){
let timer=null
return function(...args){
let content=this
if(!timer){
timer=setTimeout(function(){
fn.apply(content,args)
timer=null
},wait)
}
}
}