1. 是什么?
是优化高频率执行代码的一种手段。
比如:浏览器的 resize 、scroll 、keypress 、mousemove 等,在连续被触发时会不断的调用绑定在事件上的回调函数,非常浪费资源和前端性能!
为了优化用户体验,需要对这类事件进行限制调用的次数,我们可以采用 throttle (防抖)和 debounce (节流)的方式减少被触发的频率。
1.1. 定义
- 节流:n秒内只运行一次,在n秒内重复被触发,只生效一次
- 防抖:n秒后执行该事件,在n秒内被重复出发,则重新计时
简单来说,防抖就是游戏里的回城,点击后在点击会重新计时回城时间,节流就是放技能,一段时间内只能放一次
2.代码实现
2.1 节流
思路:每次事件被触发时,如果函数没有在指定的时间间隔内被调用,则调用函数并设置一个计时器,在指定的时间内不在再触发该事件,如果在指定事件内触发事件,则不调用函数,直到间隔时间过去,再重新调用函数
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<style>
.box {
width: 300px;
height: 300px;
background-color: #ccc;
margin: 100px auto;
text-align: center;
color: #fff;
font-size: 50px;
align-self: center;
}
</style>
</head>
<body>
<div class="box">0</div>
<script>
let count = 0
let flag = true
document.querySelector('.box').addEventListener('mousemove',function () {
if(flag){
this.innerHTML = ++count
flag = false
setTimeout(function () {
flag = true
},500)
}
})
</script>
</body>
</html>
2.2 防抖
思路:每次事件触发时,设置一个定时器,在指定时间内再次被触发,则重新计时,直到时间间隔内有再次触发事件,然后再调用函数
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<style>
.box {
width: 300px;
height: 300px;
background-color: #ccc;
margin: 100px auto;
text-align: center;
color: #fff;
font-size: 50px;
align-self: center;
}
</style>
</head>
<body>
<div class="box">0</div>
<script>
let count = 0
let timeId
document.querySelector('.box').addEventListener('mousemove',function () {
clearTimeout(timeId)
timeId = setTimeout( () => {
this.innerHTML = ++count
},500)
})
</script>
</body>
</html>
2.3 lodash实现防抖节流
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<style>
.box {
width: 300px;
height: 300px;
background-color: #ccc;
margin: 100px auto;
text-align: center;
color: #fff;
font-size: 50px;
align-self: center;
}
</style>
</head>
<body>
<div class="box">0</div>
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.js"></script>
<script>
let count = 0
function fn() {
this.innerHTML = ++count
}
// 节流
document.querySelector('.box').addEventListener('mousemove', _.throttle(fn, 500))
// 防抖
document.querySelector('.box').addEventListener('mousemove', _.debounce(fn, 500))
</script>
</body>
</html>
3.区别
相同点:
- 都是通过 setTimeout 是实现
- 都是减少事件触发频率,优化性能
不同点:
- 节流是在一段时间内最多触发一次,节流算法会在特定的间隔时间判断,是否触发事件
- 防抖是在一端时间内只要触发事件就会重新计时,直到这段时间没有触发,才触发事件
- 节流适用于持续触发,防抖适用于短时间内大量触发