开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第28天,点击查看活动详情
前言
我们要实现节流首先要知道节流是什么?节流就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率
有一个场景,有一个div,设置了draggable属性为true,是可以拖动的,然后js代码里获取div元素并监听它的拖拽事件,拖拽的过程中并打印offsetX和offsetY
<div class="block" draggable="true"></div>
<script>
const box=document.querySelector('.block')
box.addEventListener('drag',function(e){
console.log(e.offsetX,e.offsetY);
})
</script>
不断拖动的时候控制台一直在打印,很多时候这些打印对我们来说太频繁了,为了限制打印的频率。就可以对此进行节流
节流的实现
定义一个throttle函数来做节流,将监听函数里的function作为throttle函数的参数,并且返回一个function,就相当于每次拖拽时执行的都是throttle函数
function throttle(fn){
return function(){
}
}
box.addEventListener('drag',throttle(function(e){
console.log(e.offsetX,e.offsetY);
}))
之后需要设置一个定时器,在返回的function外面定义一个timer变量为null,它只会初始化一次,在function里设置一个定时器,设置一个延时时间,时间到了执行传进来的方法
但是我们只希望执行一次,也就是连续触发事件但是在 n 秒中只执行一次函数,于是将定时器赋值给timer,然后判断如果已经有定时任务了将在未来执行传进来方法就直接return
并在计时结束的时候执行fn()并清空timer
function throttle(fn){
let timer=null
return function(){
if(timer) return
timer=setTimeout(() => {
fn()
timer=null
}, 1000);
}
}
可以看到节流也是实现了,只执行了一次fn()
但是却出错了,无法读取未定义的属性(读取“offsetX”),只需将事件对象传给fn就行了,就可以正常打印offsetX和offsetY了
function throttle(fn){
let timer=null
return function(event){
if(timer) return
timer=setTimeout(() => {
fn(event)
timer=null
}, 1000);
}
}