开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天
在实际的前端开发中,会有一些频繁的触发事件,像resize、mousemove、mousedown、keydown、keyup等。
下面是事件频繁触发的例子:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>debounce</title>
<style>
#container{
width: 100%;
height: 300px;
line-height: 300px;
text-align: center;
background-color: #555;
color: #fff;
font-size: 30px;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
let count = 1;
const container = document.getElementById('container');
const getUserAction = () => {
container.innerHTML = count++
}
container.onmousemove = getUserAction;
</script>
</body>
</html>
通过例子可以看到鼠标的mousemove事件频繁触发了多次,这就是频繁触发的事件。
假设这个事件是一个网络请求,我们不能让它多次发送请求,就需要用到防抖函数。
防抖函数
当我们只想在一段时间内触发函数一次,就需要防抖函数。在实际开发中,搜索框、文本字段自动保存和消除双击按钮都是debounce的用例。下面是一个简单防抖函数的示例:
function debounce(func, delay) {
let timer = null;
return (...param) => {
if(timer) {
clearTimeout(timer);
}
timer = setTimeout(() => { func.apply(this, ...param); }, delay);
}
}
这就是一个简单的防抖函数,下面我们将它应用在我们上面的例子中
container.onmousemove = debounce(getUserAction, 1000);
让我们来看一下效果
可以看到mousemove事件不会频繁的触发,1秒内只会触发一次。
防抖的原理就是无论你触发多少次事件,我一定会在最新的事件触发n秒后才会执行,如果在n秒内又触发了这个事件,就以新的事件触发的事件为准,n秒后执行。
防抖函数改进
假设我们想要立刻执行函数,等到停止触发事件的n秒后,再重新触发执行函数,需要怎么处理?
需要在防抖函数里加一个immediate参数,具体改进如下所示:
function debounce(func, delay, immediate) {
let timer = null;
return (...param) => {
if (timer) {
clearTimeout(timer);
}
if (immediate) {
const callNow = !timer;
timer = setTimeout(() => { timer = null }, delay);
if (callNow) {
func.apply(this, param);
}
} else {
timer = setTimeout(() => { func.apply(this, param); }, delay);
}
}
}
我们将改进后的防抖函数运用在示例中:
container.onmousemove = debounce(getUserAction, 1000, true);
效果如下:
以上就是有关防抖函数的一些知识和例子,供自己记录和掘友们参考~