今天,小洁和小惠看了(实现)函数防抖的代码,本来是要解决防抖,我们却困惑为什么连续点击三次会执行三次定时器(希望不会有人像我们一样傻有这种困惑),下面是待解决的问题(看动图)及代码
(为了下面的一系列描述可以简单粗暴,我把网友的代码改编了一下)
代码(此处还没实现函数防抖)如下:
// Js
var count = 0;
// 防抖的重点在于闭包作用域和清除定时器
function debounce() {
consoleTime("1.debounce")
var timer; // 定时器
clearTimeout(timer); // 清除定时器
timer = setTimeout(function () {
funct();
}, 1000);
}
// 定时器要执行的函数
function funct(args) {
consoleTime("2.定时器")
console.log("----- 分割线 -----")
let testId = document.getElementById("test");
++count;
testId.innerHTML = `hello ${count}`;
}
// 打印时间
function consoleTime(text) {
let date = new Date();
console.log(text, date.toLocaleTimeString(), date.getMilliseconds());
}
// html
<button onclick="debounce()">点击</button>
待解决防抖问题.gif
敲黑板,下面进入重点了,在上述代码基础上实现函数防抖,代码如下。
业务场景:假设客户在保存表单时,然后不小心连续点击了两次保存,那么就会发送两次请求。
那么我们为了解决这个不小心连续点击发送多次请求的问题,设定1秒内不管我们点多少次,都只发送一次请求。而函数防抖就是,不管你在设定的时间内点击了多少次,只有在最后一次才执行了你的目标函数。
var count = 0;
// 防抖的重点在于闭包作用域和清除定时器
function debounce() {
var timer; // 定时器
// 重点
return function () {
consoleTime("1.闭包")
clearTimeout(timer); // 清除定时器,重点
timer = setTimeout(function () {
funct();
}, 1000);
}
}
// 定时器要执行的函数
function funct(args) {
consoleTime("2.定时器")
console.log("----- 分割线 -----")
let testId = document.getElementById("test");
++count;
testId.innerHTML = `hello ${count}`;
}
// 打印时间
function consoleTime(text) {
let date = new Date();
console.log(text, date.toLocaleTimeString(), date.getMilliseconds());
}
// 重点:先把debounce函数返回的匿名函数(闭包)赋值给一个变量
var test = debounce()
// html, 这里看清楚了,onclick绑定的是test不是debounce
<button onclick="test()">点击</button>
实现函数防抖的点击.gif
分析:
两个知识点(闭包作用域和定时器)
1、var test = debounce()
2、return function(){...}
3、clearTimeout(timer);
实现原理:
1、需要设定在某个时间内,只执行最后一次,因此用到了定时器setTimeout 来设定时间。
2、因为只执行最后一次,所以需要在每次执行之前把上一次的清除掉,因为设定时间还没到,那么定时器里的函数还没执行,所以我们清除了上一次的定时器函数就不会执行了。因此有重点3,所以每次我们都把定时器setTimeout返回的id记录下来。
3、使用闭包,是为了在它所在的作用域保存setTimeout返回的id,以便于在设定时间内点击时清除上一次的setTimeout。
4、如果onclick绑定debounce返回的匿名函数,每一次点击,debounce都会重新执行。那么clearTimeout是清除不了上一次定时器的。
5、onclick绑定test,每次点击,test()都能访问debounce()的内部作用域,所以能记录每次定时器setTimeout返回的id,并清除上一次的定时器。(闭包所在的内部作用域变量不会被回收)
本来没打算写函数防抖的,因为网上很多文章,我写这个是为了记录学习理解的内容。写着写着不会表达了,如有错误表达望指出。
网友评论