工具函数系列-防抖debounce
防抖的原理:触发事件,但在事件触发 n 秒后才执行,如果在一个事件触发的 n 秒内又触发了这个事件,那就以新的事件时间为准,n 秒后才执行。总之,就是要等触发完事件 n 秒内不再触发事件,才执行。
应用场景:input
输入
实现
function debounce(func, wait, immediate) {
var timeout = null, result;
return function() {
var context = this; // 修改this指向,避免指向window
var args = argumenets; // 传参
if (timeout) clearTimeout(timeout); // 等触发完事件n秒后执行
if (immediate) { // 立即执行第一次 immediate判断是否立即执行
// 如果已经执行过,不再执行
var callNow = !timeout; // !null = true !12 = false
timeout = setTimeout(function() {
func.apply(context, args)
}, wait)
if (callNow) { // 第一次执行
result = func.apply(context, args)
}
} else {
timeout = setTimeout(function() {
func.apply(context, args)
}, wait)
}
return result; // 只有立即执行模式才能返回结果
}
}
添加取消模式
比如说我 debounce 的时间间隔是 10 秒钟,immediate 为 true,这样的话,我只有等 10 秒后才能重新触发事件,现在我希望有一个按钮,点击后,取消防抖,这样我再去触发,就可以又立刻执行了
function debounce(func, wait, immediate) {
var timeout = null, result;
var debocunced = function() {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(function() {
func.apply(context, args)
}, wait)
result = callNow ? func.apply(context, args) : undefined;
} else {
timeout = setTimeout(function() {
func.apply(context, args)
}, wait)
}
return result;
}
debounced.cancel = function() {
clearTimeout(timeout)
timeout = null
}
return debounced;
}
参考文章:https://github.com/mqyqingfeng/Blog/issues/22
测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="IE=edge, chrome=1">
<title>debounce</title>
<style>
#container{
width: 100%; height: 200px; line-height: 200px; text-align: center; color: #fff; background-color: #444; font-size: 30px;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
var count = 1;
var container = document.getElementById('container');
function getUserAction() {
let num = count++
container.innerHTML = num;
console.log(Date.now(), num)
};
container.onmousemove = debounce(getUserAction, 1000);
// function debounce()...
</script>
</body>
</html>