应用场景浏览器
咱们常常须要监听滚动条滚动或者鼠标的移动,可是浏览器触发这类事件的频率很是高,可能10几毫秒就触发一次,有的时候咱们只须要处理函数执行一次,好比文本输入验证,执行屡次处理函数反而不必。闭包
常规实现,以监听 scroll 事件为例app
window.onscroll = function () {
//滚动条位置
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
解决方法:函数
减小DOM操做的频度,也就是稀疏处理函数的执行频率,解决方法就是函数防抖以及函数分流。函数防抖表示只执行一次处理函数,函数分流指下降处理函数的执行频率。this
指屡次触发事件后,事件处理函数只执行一次。具体思路就是延迟处理函数,若是设定的时间到来以前又一次触发了事件,就清除上一次的定时器,从新定时。spa
简单来讲,就是当一个动做连续触发时,只执行最后一次。code
简单实现的例子:blog
window.onscroll=function(){ if(timer){ clearTimeout(timer); } timer=setTimeout(function(){ let scrollTop=document.body.scrollTop||document.documentElement.scrollTop; console.log('滚动位置:'+scrollTop); timer=undefined; },200); }
这里有一个保存timer的技巧,若是不保存timer,那么执行完事件处理函数,timer将被销毁,咱们也就没法再清除定时器了,因此要保存这个变量,即便他所在的函数做用域对应的函数已经执行完了。事件
防抖函数的封装使用 闭包图片
//封装方法之闭包 //闭包:若是想让一个函数执行完,函数内的某个变量(timer)仍然保留。就能够用闭包 function debounce(method,delay){ var timer=null; return function(){ var that=this; var args=arguments; clearTimeout(timer); timer=setTimeout(function(){ method.apply(that,args); },delay); } } window.onscroll=debounce(function(){ var scrollTop=document.body.scrollTop||document.documentElement.scrollTop; console.log(scrollTop); },200);
应用场景:
(1)搜索框输入。只需用户最后一次输入完,在发送请求;
(2)手机号、邮箱验证输入检测;
(3)窗口大小Resize。只需窗口调整完成后,计算窗口大小,防止重复渲染。
不适用:作图片懒加载时,须要经过滚动位置实时显示图片时,若是使用防抖函数,懒加载函数就会不断被延迟,只有停下来的时候才会被执行,防抖函数对于这种须要实时触发事件的状况就显得不是很友好了。
触发事件函数后,短期内没法连续调用,只有上一次函数执行后,过了规定的时间间隔,才能进行下一次的函数调用。
原理:对处理函数进行延时操做,若设定的延时到来以前,再次触发事件,则清除上一次的延时操做定时器,从新定时。
简单实现的例子:
var startTime=Date.now();//开始时间 var time=500;//间隔时间 var timer; window.onscroll=function throttle(){ var currentTime=Date.now(); if(currentTime-startTime>=time){ var scrollTop=document.body.scrollTop||document.documentElement.scrollTop; console.log('滚动位置:'+scrollTop); startTime=currentTime; } else{ clearTimeout(timer); timer=setTimeout(function(){ throttle(); },50); } }
节流函数的封装使用 闭包
/** * 函数节流throttle * @param method事件触发的操做 * @param delay延迟执行函数的时间 * @param mustRunDelay超过多长时间必须执行一次函数 */ function throttle(method,delay,mustRunDelay){ var timer=null;//计时器 var args=arguments; var startTime=0;//开始时间 var currentTime=0;//当前时间 return function(){ var that=this; currentTime=Date.now(); if(!startTime){ startTime=currentTime; } if(currentTime-startTime>=mustRunDelay){ method.apply(that,args); startTime=currentTime; } else{ clearTimeout(timer); timer=setTimeout(function(){ method.apply(that,args) },delay); } } } window.onscroll=throttle(function(){ var scrollTop=document.body.scrollTop||document.documentElement.scrollTop; console.log(scrollTop); },50,500);
应用场景:
(1)滚动加载,加载更多或滚动到底部监听;
(2)高频点击提交,表单重复提交 。
函数防抖与函数分流的思想都是经过设置定时器控制函数的执行频率。
区别:
(1)函数防抖在一段连续的操做结束后,处理回调函数,利用setTimeout和clearTimeout实现;
函数节流在一段连续的操做中,每一段时间只执行一次。
(2)函数防抖关注必定时间连续触发,只在最后执行一次,而函数节流侧重于一段时间内只执行一次。