防抖与节流形成过程
首先在介绍防抖与节流之前,我们要清楚为什么我们需要它们?
在前端有许多高频事件比如 onscroll oninput resize onkeyup keydown...,这样执行频率比较高,还比如有一些输入框联想查询,我们不需要一输就发送ajax,我们要等待输入稳定时在进行输入,这是我们想要的。。
scroll和resize行为也会导致页面不断的重新渲染,如果在绑定的回调函数中大量操作dom会导致出现页面卡顿。。
这些都需要我们进行优化,这时候防抖(throttle),节流(debounce)就出现了
函数节流(Throttle)
节流就是保证一段时间内,核心代码只执行一次 打个比方:水滴积攒到一定重量才会下落
简易节流函数
<button id="btn">快速点击</button>
实现一秒内点击一次
let btn = document.getElementById('btn');
function throttle(func,wait){
let previous = 0;
return function(){
let now = Date.now();
if(now - previous > wait){
func.apply(this,arguments);
previous = now;
}
}
}
function logger(){
console('logger')
}
btn.addEventListener('click',throttle(logger,1000));
节流函数完整版
// 实现了 trailing 最后一次点出会触发事件,leading:第一次点击不生效
let btn = document.getElementById('btn');
function throttle(func,wait,options){
// trailing 最后一次触发
let args , context,previous = 0,timeout; //将参数,函数上下文进行保存
let later = function (){
previous = options.leading === false ? 0:Date.now();
func.apply(context,args);
args =context = null;
}
let throttled = function(){
args = arguments;
context = this;
let now = Date.now();
if(!previous && options.leading === false) previous = now;
let remain = wait - (now - previous);
if(remain <=0){ //第一次
if(timeout){
clearTimeout(timeout);
timeout = null;
}
func.apply(context,args);
previous = now;
}else if(!timeout && options.trailing !== false){ //最后一次点出会触发事件
timeout = setTimeout(later,remain);
}
}
return throttled;
}
function logger(){
console('logger')
}
// leading:false :第一次点击不生效
btn.addEventListener('click',throttle(logger,1000,{ leading:false }));
函数防抖(Debounce)
防抖就是一段时间结束后,才能触发一次,如果一段时间未结束再次触发,就会重新开始计算时间。 打个比方: 你在做电梯,门快要关了,突然有人准备上来。电梯门会重新打开,延迟了电梯门关闭时间,上来之后就重新关闭。
防抖函数
function debouce(func,wait,immediate){
let timeout;
return function(){
clearTimeout(timeout); //重新开始计时
if(immediate){
let collNow = !time;
if(collNow) func.apply(this,arguments);
}
timeout = setTimeout(()=>{
func.apply(this,arguments);
},wait)
}
}
function logger(){
console('logger')
}
// 第三个参数表示首次先触发一下
btn.addEventListener('click',debounce(logger,1000,true)