防抖、节流
window.onload=function(){
let btn=document.getElementsByTagName('button')
btn[0].addEventListener('click',()=>{
setTimeout(()=>{
alert('点击成功')
},3000)
})
}
问题:以上操作在点击一次后,如果多次点击,将会多次触发。如果是向后端发送请求,将会造成浪费等问题。
防抖
动作发生后一定时间内再次触发,将取消上一次触发
let btn=document.getElementsByTagName('button')
let timer=null
btn[0].addEventListener('click',()=>{
clearTimeout(timer)
timer=setTimeout(()=>{
alert('点击成功')
},2000)
})
封装防抖
let btn=document.getElementsByTagName('button')
btn[0].addEventListener('click',debounce(submit))
function submit(){
console.log('已提交');
}
function debounce(fn){
let timer=null // debounce函数会直接执行,而不是点击了btn才执行,此时的this时window
return function(){
if(timer){
clearTimeout(timer)
}
let _this=this // 此时的this为触发事件的元素,拿到该button。
let args=arguments // 拿到需要传入submit的参数
timer=setTimeout(function(){
fn.apply(_this,args) // 因为点击submit时,this指向button,而不是window(定时器函数是window调用的)
},1000)
}
}
节流
动作第一次触发后,在一定时间内再次触发视为无效
方式一:标志位
let flag=false
btn[0].addEventListener('click',()=>{
if(flag)
return
flag=true
setTimeout(()=>{
alert('点击成功')
flag=false
},2000)
方式二:时间戳
let btn=document.getElementsByTagName('button')
let activeTime=0;
btn[0].addEventListener('click',()=>{
let currentTime=Date.now()
console.log(currentTime,activeTime);
if(currentTime-activeTime>3000){
setTimeout(()=>{
alert('点击成功')
},3000)
activeTime=Date.now()
}
})
封装节流函数
// 方法一:时间戳
function throtte1(fn){
let active=0
return function(){
let now=Date.now()
if(now-active>1000){
fn.apply(this,arguments) // 此时的this就是button
active=Date.now()
}
}
}
// 方法二:标志位
function throtte2(fn){
let flag=true
return function(){
if(flag){
fn.apply(this,arguments)
flag=false
setTimeout(()=>{
flag=true
},1000)
}
}
}