为什么需要节流和防抖
一些浏览器事件,比如window.onresize、window.mousemove等触发频率很高,会造成页面卡顿。如果在这些事件里面向后台发送请求,会对服务器造成不必要的压力。
那么限制事件处理函数频繁调用的方法就是节流throttle和防抖debounce
函数节流(throttle)
概念:当函数执行完一次之后,只有大于设定的执行周期才会执行第二次,适合多次事件按时间做平均触发。(两次操作间隔一个已经确定的周期,第二次操作就会被执行)通俗来讲可以把事件的频繁发生看成一个水流,原来的流速是100次/s,节流之后可以实现10次/s。
场景:
窗口调整(resize)、页面滚动(scroll)、DOM元素的拖拽(mousemove)、抢购疯狂点击(click)
手写实现(在wait内最多执行一次callback)
window.addEventListener('scroll',throttle(function(e){
console.log(e)},500)
);
function throttle(callback,wait){
//定义开始时间
let start = 0;
//返回一个函数
return function(...args){
//获取当前时间戳
let now = Date.now();
if(now - start >= wait){//如果大于执行周期
//this指向当时的事件源
callback.apply(this,args);
start = now;
}
}
}
防抖debounce
概念:两次操作间隔时间小于我们设定的定时器的时间就不执行。(短时间内多次触发事件,只执行最后一次)
场景:表单输入验证、表单输入触发搜索 ajax、resize/scroll/touch/mouseove 事件
let input = document.querySelector('input');
input.oninput = debounce((e) =>{
console.log(e.target.value);
},500)
function debounce(callback,time){
//定时器变量
let timeId = null;
//返回一个函数
return function(...args){
//当有一个定时器在跑的时候
if(timeId != null){
//清空定时器
clearTimeout(timeId);
}
//启动定时器 返回一个数字
timeId = setTimeout(()=>{
callback.apply(this,args);
//重置定时器变量
timeId = null;
},time)
}
}