一、节流(Throttle)
无论节流还是防抖,我们都会在事件的处理函数中去统计时间判断,那函数内部有,每一次执行函数,都会对内部变量进行一个判断,这个变量在函数执行之后,不应该被销毁,所以这里用到闭包
场景:
- 页面有一个按钮,用户疯狂点点点,每点一次,都要触发一次处理函数,服务器承受不了
- 鼠标不断点击触发,mousedown(单位时间内只触发一次) mousemove事件
有两种主流的实现方式,一种是使用时间戳(好理解),一种是设置定时器(较麻烦)。
这里我使用时间戳实现节流函数 每隔固定的时间处理函数
代码:
<body>
<button>按钮</button>
<script>
// 时间戳实现节流函数:
function throttle(fn, delay) {
var previous = 0;
// 使用闭包返回一个函数并且用到闭包函数外面的变量previous
return function () {
var now = new Date(); //拿到当前的时间
if (now - previous > delay) {
// 每次触发事件的时候,都会拿到一个当前的时间
//当前时间-调用函数最开始的时间 如果超过固定间隔时间
fn(); //执行处理事件
previous = now; //将当前触发事件的时间 赋值 成 当前事件首次触发的时间
}
};
}
document.querySelector("button").onclick = throttle(function () {
console.log(1);
}, 2000);
</script>
</body>
示意图:这里时间间隔我设置成了2s
二、防抖(Debounce)
场景:
1.search搜索框输入,只需用户最后一次输入完在发送请求。
2.表单的按钮提交事件,例如登录,发短信,避免用户点击太快,以至于发送了多次请求,加大服务器的压力
代码:
<body>
<button>按钮</button>
<script>
// 防抖方法: 使用闭包,操作同一个timer:只有最后一次操作生效
// 触发时,创建定时器,当发现定时器存在就清除当前定时器,创建新的定时器
//首次触发的时候 会创建一个setTimeout去等 此时如果再次触发 将timer清除
function debounce(fn, delay) {
var timer;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
fn();
}, delay);
};
}
document.querySelector("button").onclick = debounce(function () {
console.log(1);
}, 2000);
</script>
</body>
示意图:这里的时间间隔设置成2s
说明:就是频繁点击时,会消除上一次的timer,创建自己的timer,等到最后一次点击时,比方说操作了8次,第七次timer被清除了,由于没有再触发Debounce防抖函数,就没有再创建timer,这个timer一直存在,等到时间间隔,就会去执行fn()
<body>
<span>0</span>
<button>点击我+1</button>
<script>
var count = 0;
let button = document.querySelector('button')
let span = document.querySelector('span')
// 手写节流
button.onclick= debounce(function(){
count++;
span.innerHTML=count
},1000)
节流
function throttle (fn,delay){
var previous = 0;
return function(){
var now = new Date();
if(now-previous>delay){
fn();
previous = now
}
}
}
function debounce(fn,delay){
var timer = null;
return function(){
if(timer){
clearTimeout(timer)
}
timer=setTimeout(function(){
fn()
},delay)
}
}
</script>
</body>