什么是防抖
防抖,顾名思义就是防止抖动,避免事件的重复触发
防抖的应用场景
我们使用网页时,经常会操作一些高频触发的事件,比如,用户正在使用搜索框输入关键字的时候,用户的每一次输入都会触发输入框的oninput事件,如果每次输入都向服务器发送请求来获取数据,会给服务器造成不必要的负载。而防抖就可以将一定时间内的多次触发合并为一次,只监听用户的最后一次输入,就只用向服务器发送一次请求,从而达到减少请求次数和服务器负载的效果。
防抖的设计思路
防抖的代码实现
这里我用一个简单的小案例来演示防抖的具体写法
未设置防抖
在网页中生成一个盒子,并给盒子绑定鼠标移动事件,当鼠标在盒子内移动,盒子内的数字加1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 500px;
height: 500px;
background-color: #ccc;
color: #fff;
text-align: center;
font-size: 100px;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
// 获取dom元素
const box = document.querySelector('.box')
// 绑定事件
box.addEventListener('mousemove', e => {
// 业务代码:数字加1
box.innerText++
})
</script>
</body>
</html>
可以看到,由于没有设置防抖,鼠标在盒子内的每一次移动都触发了数字加1的业务
设置防抖
根据我们上面防抖的设计思路,我们先将1秒的 延时器 和 延时器id 设置好,再将业务代码放到延时器代码里面,如果事件多次触发,就使用 ClearTimeout(延时器id) 清除上一个延时器,再开启下一个延时器。
<script>
// 获取dom元素
const box = document.querySelector('.box')
// 设置延时器id
let timeId
// 绑定事件
box.addEventListener('mousemove', e => {
// 清除延时器
clearTimeout(timeId)
// 设置延时器1秒后触发
timeId = setTimeout(() => {
// 业务代码:数字加1
box.innerText++
}, 1000)
})
</script>
在设置防抖后,鼠标在盒子内的连续移动并不会触发数字加1的业务,而当鼠标停下时,在停下之前的 最后一次 移动则会触发数字加1,这样就实现了防抖的功能。
更多写法
我们除了使用js原生的延时器来实现防抖之外,还可以使用 Lodash工具库 来实现。Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。
在VS Code中引入js文件
<script src="lodash.js"></script>
再使用Lodash已经封装好的写法 _.debounce 来实现防抖。
<script>
// 获取dom元素
const box = document.querySelector('.box')
// 定义函数fn
function fn() {
// 业务代码:数字加1
box.innerText++
}
// 声明变量newFn
const newFn = _.debounce(fn, 1000)
box.addEventListener('mousemove', newFn)
</script>
另外还有一种更加简洁的写法
<script>
// 获取dom元素
const box = document.querySelector('.box')
// 绑定事件的同时使用_.debounce方法
box.addEventListener('mousemove', _.debounce(() => {
box.innerText++
}, 1000))
当然,简洁的代码往往会牺牲一些可读性,以上三种写法怎么选择,要根据实际工作需求来判断。
总结
当用户在一定时间内高频触发事件,可以使用防抖只监听最后一次触发,达到以降低服务器负载的目的。