一、防抖(debounce)
如果想要实现点击按钮不是一直触发事件。
<button id="btn">点击我!</button>
<script>
var n = 0
document.getElementById('btn').addEventListener('click', show )
那么可以在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms,然后:
如果在200ms内没有再次触发滚动事件,那么就执行函数
如果在200ms内再次触发滚动事件,那么当前的计时取消,重新开始计时
效果:如果短时间内大量触发同一事件,只会执行一次函数。
实现:既然前面都提到了计时,那实现的关键就在于setTimeOut这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现:
//实现一个防抖函数,规定时间里触发多次只会执行一次
function debounce(fn, delay) {
let timer = null
// 使用闭包保存这个计时器
return function () {
if (timer) {
//到这里说明规定时间里再次触发了事件,重新计时
clearTimeout(timer)
}
// 否则生成计时器
timer = setTimeout(fn, delay)
}
}
原来的代码修改如下:
document.getElementById('btn').addEventListener('click', debounce(show, 2000)
这样就不会一点就触发啦!
但是如果用户一直点击着按钮,永远都不会触发事件。
想要让用户即使一直按着按钮不妨也会看到事件触发的效果,那么可以使用节流函数。
二、节流函数
可以设计一种类似控制阀门一样定期开放的函数,也就是让函数执行一次后,在某个时间段内暂时失效,过了这段时间后再重新激活(类似于技能冷却时间)。
效果:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。
实现 这里借助setTimeout来做一个简单的实现,加上一个状态位valid来表示当前函数是否处于工作状态:
function throttle(fn,delay){
let valid=true;
return function(){
//技能冷却状态,暂时不能触发事件
if(!valid) {
return false
}
//可以发大招了
valid=false//修改状态
setTimeout(()=>{
fn()
valid=true//时间到了可以再次触发
}, delay);
}
}
原代码可以修改为:
document.getElementById('btn').addEventListener('click', throttle(show, 2000)
就可以实现一直按着按钮依然可以每隔2s触发一次事件!