javascript 中的防抖和节流
防抖和节流的使用场景
在javascript 中经常会用到一些监听事件,比如 scrollView 、mousemove 等事件。在使用这些事件的回调函数时,如果回调逻辑复杂一些,就会导致页面卡顿。 那么使用防抖和节流就能有效提升页面流畅度。除了上述的事件,也可用于多次点击事件等。
防抖和节流的介绍
防抖和节流一般需要使用setTimeout 方法
防抖(debounce)
防抖是指在多次调用时,只在最后一次调用回调时生效。需要使用setTimeout
定义一个超时时间。如果在超出时间内又触发了防抖事件,那么就会使定时器重新计时。
var timeout = null // 定义定时器对象
// 在body 元素上监听鼠标移动事件
document.body.onmousemove = (e) => {
// 判断定时器是否存在
if (timeout) {
// 清除上一个计时器
clearTimeout(timeout)
}
timeout = setTimeout(() => {
console.log('mouseMove') // 结束移动打印一次 mouseMove
}, 500)
}
上方的代码在body内监听mousemove
事件,如果不加定时器,只要你鼠标在body上移动,控制台就会打印非常多的 "mouseMove"
但是加了防抖后,变为了只在鼠标结束移动后才执行定时器内的代码。
mousemove 为鼠标移动事件 clearTimeout 方法将会清除定时器
节流(throttle)
节流是指在多次调用时,限制调用的频率,比如在mousemove
事件中,我们不需要鼠标停止移动时执行操作,而是限制每500毫秒进行一次操作:
var timeout = false // 定义延迟状态
// 在body 元素上监听鼠标移动事件
document.body.onmousemove = (e) => {
// 如果还没到延迟时间就 rertun
if (timeout) {
return false
}
// 设置延迟开始
timeout = true
setTimeout(() => {
console.log('mouseMove') // 500ms打印一次 mouseMove
// 执行代码完成 清空延迟
timeout = false
}, 500)
}
稍微改动下代码,根据timeout
变量判断是否可以执行代码。只有在执行完一次定时器任务后才进行下一个定时器任务,稀释了高频触发的回调。运行代码就会发现只要鼠标保持移动,那么控制台上就会一直打印,打印的频率就是定时器的执行延迟。
防抖和节流的区别
- 防抖在一次高频事件中只在超出延迟时间后触发,大幅度减少了cpu运算的次数。
- 节流简单来讲就是把原来很快触发的高频事件变成自定义触发时间,稀释cpu的运算次数。
总的来说防抖对性能的优化更好,但是连贯性不强。节流虽然计算次数更多,但是能给用户带来更加连贯的体验。
比如需要做一个图片跟随鼠标的功能,用防抖的话就会导致只在鼠标停止移动后图片移动,但是用节流函数就能保证一边移动鼠标一边图片跟随移动。
总结
在开发中我们还是需要更具对应的需求来选择防抖还是节流。
在一些需要持续变动的需求时可以用节流,比如跟随鼠标功能、页面变更尺寸改变dom大小等。
在一些需要防止重复操作的需求时,可以用防抖。比如 表单提交之类的按钮事件,重复点击的话我们不需要多次进行回调,那么我们显然是用防抖更好。
以上是个人对防抖节流的学习和看法,希望有帮助到各位。
有相关问题欢迎在评论区进行讨论!