在使用js操作dom元素进行交互时,如何提高性能,节约资源是一个绕不开的话题,而节流和防抖这两个十分相像的概念在其中扮演重要的角色。本文将探讨节流和防抖分别是什么,怎样实现,以及案例分析,来提高你对这两种技术的认知~
一、防抖
所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会取消上次没执行完的重新计算函数执行时间。这样就可以避免资源重复加载所造成的浪费。
即“单位时间内多次触发只执行最后一次”。
下面用一个案例来分析:鼠标在盒子上移动,每移动一像素盒子上的计数就会加一,导致计数过于敏感。要求使用防抖技术,使得只有在鼠标停止移动500ms后,里面的数字才会变化+1。
1.使用lodash库实现
lodash库是一个高性能的js使用工具库,其中集成了许多js常见数据类型的处理方法,调用lodash库中的_.debounce函数可以高效实现防抖。
_.debounce(fun,[wait=0],[options=])
<style>
div {
width: 200px;
height: 200px;
background-color: #b58383;
font-size: 30px;
text-align: center;
line-height: 200px;
}
</style>
<div class="box"></div>
<script src="/js_exercise/lodash.min.js"></script>
<script>
const box = document.querySelector('.box')
let i = 1
function mouseMove() {
box.innerHTML = i++
}
box.addEventListener('mousemove', _.debounce(mouseMove, 500))
</script>
2.手写防抖函数
也可以模仿上面的_.debounce函数,写一个自己的防抖函数。
-
利用setTimeout来实现
-
利用定时器实现,当鼠标滑过,判断有没有定时器,还有就清除,以最后一次滑动为准开启定时器
⑥: 如果有定时器,则清除定时器
⑦: 否则开启定时器, 在设定时间内,调用函数
const box = document.querySelector('.box')
let i = 1
function mouseMove() {
box.innerHTML = i++
}
box.addEventListener('mousemove', debounce(mouseMove, 500))
function debounce(fn, t) {
let timer
//返回一个匿名函数
return function () {
if (timer) { clearTimeout(timer) }
timer = setTimeout(function () {
fn()
}, t)
}
}
note:思考为什么要返回一个匿名函数呢?
因为addEventListener里的函数带了小括号,会立即执行一次,因此页面一打开就执行完毕了,鼠标再滑动就不会执行了。而返回一个匿名函数就使得debounce(mouseMove, 500)=function,就不会再立即执行了。
二、节流
实现单位时间之内 只能触发一次鼠标移动事件
类似于技能冷却时间,触发一次后,在规定时间内再触发就无效了。
1.lodash节流函数
_.throttle(fun[,wait=0],[options=])
500ms之内mouseMove函数只能调用一次
const box = document.querySelector('.box')
let i = 1
function mouseMove() {
box.innerHTML = i++
}
box.addEventListener('mousemove', _.throttle(mouseMove, 500))
2.手写节流函数
const box = document.querySelector('.box')
let i = 1
function mouseMove() {
box.innerHTML = i++
}
box.addEventListener('mousemove', throttle(mouseMove, 500))
function throttle(fn, t) {
let timer
//返回一个匿名函数
return function () {
if (!timer) {
timer = setTimeout(function () {
fn()
//清空定时器,注意这个清除方式
timer = null
}, t)
}
}
}
note:clearTimeout不能在定时器的回调function函数里调用来关闭自己
因此我们使用了赋值方法,timer=null来清除计时器!
三、二者的使用场景
1.‘防抖’
顾名思义,就是防止用户操作时发生抖动,从而触发非必要的多次事件。因此用在‘连续的事件’上,例如:
- 搜索框输入:设定需用户最后一次输入完毕一定时间后再向后台发送请求
- 计算窗口大小从而渲染页面:在窗口大小停止变化一定时间后再计算和渲染
- 输入表单是否合法的检测:
2.‘节流’
用于限定开销较大的情况,避免资源刷新过快。例如:
- 加载更多:一定时间内只能加载资源一次
- 滚动条滚动:
以上就是对这两种技术的介绍了~他们的实际应用场景和实现方法并非是固定不变的,需要具体分析想要的效果,再来选择和编码。这也体现了计算机算法的灵活性,作为一门‘人’发明的学科,它的规则是不断在进步的。提醒小伙伴们学习时一定要多多思考,拒绝生搬硬套!