当前位置: 首页 > Web前端 > JavaScript

自定义防抖函数五步应对复杂需求

时间:2023-03-27 10:07:08 JavaScript

五步自定义防抖功能,应对复杂需求不会立即触发,会等待。只有等待一段时间,事件停止触发,才会执行响应函数。防抖案例:比如屏幕设置了1分钟熄屏,如果用户在这1分钟内没有对电脑进行任何操作,那么电脑会在1分钟内定时熄屏分钟,但如果用户秒,移动鼠标,则从此时开始重新开始熄屏时间,1分钟内无操作继续熄屏。防抖使用场景在程序设计过程中,“防抖”可以用在很多场景中。频繁在输入框输入,频繁点击搜索按钮,提交信息触发事件。监听浏览器的滚动事件,监听浏览器的缩放事件。不使用防抖时,这里模拟一个商品搜索框。我们需要关联用户的内容调用接口。查询给用户搜索提示。不使用防抖时,我们直接将函数绑定到对应的事件上。//html代码//js代码constinputEl=document.querySelector('input')letcount=0constinputChange=function(){console.log(`${++count}调用inputChange方法`)}inputEl.oninput=inputChangeInput输入框中的“javascript”,一共10个字符,所以该方法被调用了10次。这种方法的性能非常低。一是每输入一个字符就调用一次接口,给服务器带来很大的压力,二是因为用户直到第10个字符才停止输入,此时就获取了用户输入的完整信息,前9个字符的调用就没有那么必要了。那么,“防抖”的作用就是等到用户停止输入时,再执行该功能,避免多次执行造成的资源浪费。自定义防抖功能防抖功能的原理是传入要执行的函数,以及等待延时的时间,经过一系列处理后执行传入的函数。第一步:基本防抖实现定义setTimeout来延迟函数的执行时间。clearTimeout用于在输入下一个字符超过1秒时清除定时器,并创建一个新的定时器。如果不清除,相当于每个字符每隔1s调用一次方法。constdebounce=function(fn,delay){让定时器=null;const_debounce=function(){if(timer)clearTimeout(timer);timer=setTimeout(()=>{fn()},延迟);};return_debounce;};inputEl.oninput=debounce(inputChange,1000);我们希望在用户输入完成时执行该函数,即输入10个字符后调用一次。但是这个时候,我们发现了那个event.target。value用于获取用户输入的值,变为undefined第二步:展开this和parameters上一步定义函数时,丢失了this对象和event参数。要让他们回到这里,只需要在执行使用fn函数时,改变this的执行方式,通过call/apply/bind传入参数即可。constdebounce=function(fn,delay){让定时器=null;const_debounce=function(...args){if(timer)clearTimeout(timer);timer=setTimeout(()=>{fn.apply(this,args)},delay);};return_debounce;};inputEl.oninput=debounce(inputChange,1000);这之后我们就可以获取到用户的输入了~至此,防抖已经实现了一些使用场景,我们来看更复杂的需求~第三步:函数立即执行在我们定义的防抖函数中上面,不是立即执行的,即输入第一个字符“j”时,不会调用函数,可能有一些场景,等到用户输入完成再调用响应比较慢,需要输入第一个字符时调用一次。这里可以给传入的函数加一个参数,表示是否需要立即执行。默认情况下,它是假的。函数中使用一个变量来保存是否需要第一次执行。第一次执行完成后,将此变量设置为false。constdebounce=function(fn,delay,isImmediate=false){lettimer=null;让isExcute=isImmediate;const_debounce=function(...args){if(isExcute){fn.apply(this,args);isExcute=false;}如果(计时器){clearTimeout(计时器);}timer=setTimeout(()=>{fn.apply(this,args);isExcute=isImmediate;},delay);};return_debounce;};inputEl.oninput=debounce(inputChange,1000,true);输入字符“j”时立即调用,用户输入完成时调用一次,所以这里会有两次调用。第4步:仔细查看取消功能。我们的防抖功能无法取消。时间一到就会执行。万一用户输入完内容,还不到1秒,他就关闭了窗口。好吧,考虑到这种情况,我们不得不安排取消功能!函数也是一个对象,我们可以在函数对象上绑定另一个函数,在return的_debounce上绑定一个cancel方法,需要取消的时候执行cancel方法//html//javascriptconstcancelBtn=document.querySelector("按钮");constdebounce=function(fn,delay,isImmediate=false){lettimer=null;让isExcute=isImmediate;const_debounce=functionEx(...args){可爱if(is){fn.apply(this,args);isExcute=false;}如果(计时器){clearTimeout(计时器);}timer=setTimeout(()=>{fn.apply(this,args);isExcute=isImmediate;},delay);};_debounce.cancel=function(){if(timer){clearTimeout(timer);}};return_debounce;};constdebounceFn=debounce(inputChange,2000,true);inputEl.oninput=debounceFn;cancelBtn.onclick=debounceFn.cancel;输入内容时,停止输入到点击按钮的时间不超过定义的时间(上面定义为2秒),这样只会执行第一次输入的函数,完成用户输入届时将不会执行。第五步:函数返回值上面定义的“防抖”函数没有返回值。如果想在执行完成后获取执行结果,在防抖功能的输入中有两种获取回调函数的方法。parameters中加入第四个参数,是获取防抖功能执行结果的函数letcount=0;constinputChange=function(event){console.log(`${++count}call,输入内容为:${event?.target?.value}`);返回'你好世界'};constdebounce=function(fn,delay,isImmediate=false,callbackFn){lettimer=null;让isExcute=isImmediate;const_debounce=function(...args){if(isExcute){constresult=fn.apply(this,args);callbackFn(result)isExcute=false;}如果(计时器){clearTimeout(计时器);}timer=setTimeout(()=>{constresult=fn.apply(this,args);callbackFn(result)isExcute=isImmediate;},delay);};返回_debounce;};constdebounceFn=debounce(inputChange,2000,true,function(result){console.log('获取执行结果',result)});inputEl.oninput=debounceFn;每次执行debounce函数,都会执行回调函数中的内容。在promise防抖函数的返回函数中,通过promise返回成功或者失败的结果。下面的代码只判断执行成功的条件,也可以加上失败的处理。需要调用promise包裹的异步函数获取响应结果,所以防抖功能放在new函数中,new函数作为oninput事件响应函数。constinputEl=document.querySelector("input");让计数=0;constinputChange=function(event){console.log(`第${++count}次调用,输入的内容为:${event?.target?.value}`);返回“你好世界”;};constdebounce=function(fn,delay,isImmediate=false){lettimer=null;让isExcute=isImmediate;const_debounce=function(...args){returnnewPromise((resolve,reject)=>{if(isExcute){constresult=fn.apply(this,args);resolve(result);isExcute=false;}if(timer){clearTimeout(timer);}timer=setTimeout(()=>{constresult=fn.apply(this,args);resolve(result);isExcute=isImmediate;},delay);});};//封装取消消能_debounce.cancel=function(){if(timer)clearTimeout(timer);计时器=null;isInvoke=假;};返回_debounce;};常量debounceFn=去抖动(inputChange,2000,真);constpromiseCallback=function(...args){debounceFn.apply(inputEl,args).then((res)=>{console.log("promise执行结果",res);});};inputEl.oninput=promiseCallback;传入回调函数的形式是一样的,每次执行防抖功能都会返回一个结果。在开发过程中使用防抖功能来优化项目的性能,可以按上面的方式自定义,也可以使用第三方库。以上就是与防抖功能相关的内容。关于高级js,开发者需要掌握的东西还是很多的。可以看看我写的其他博文,正在更新中~