前戏 首先,总结一下上一篇文章——《前端 JavaScript 之『防抖』的简单代码实现》的内容:「防抖」就是在高频率触发事件停止触发后,延时执行某个处理逻辑。
防抖虽然在一定程度上对性能起到了优化效果,但是,我们也要看到它的局限性:如果高频率事件一直触发,那么回调函数中的逻辑就一直得不到执行。
大家都知道,掘金的编辑器带有草稿箱的效果,即你输入的内容会保存下来,即使我们退出编辑器页面了,再次进入还是可以找回前面输入的内容,这是因为编辑器的 input 事件中执行了发送内容的防抖函数。如下图所示:
现在假设:你的打字速度很快,基本上不带喘口气的,那么是否会导致很长时间都保存不了一次数据?如果这时候你再以迅雷不及掩耳之势关闭掉浏览器,是不是你所写的内容就保存不下来了?
那么我们是否可以想办法避免上面这种情况呢?
在这种需求背景下,我们今天的主人公——「节流」开始粉墨登场。
节流的含义大家应该都知道了:每隔固定的时间都会执行一次回函函数中的逻辑 。
不使用节流函数,我们来看一下下面这个功能的执行效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <body > <form action ="" class ="example-form" > <div > <label for ="name" > 名称 </label > <input class ="input-ele" type ="text" name ="name" id ="name" placeholder ="please input your name" autocomplete ="off" > </div > <div > <label for ="res" > 输入 </label > <textarea class ="input-ele" type ="multipart" name ="res" id ="res" readonly placeholder ="这里是每一次输入的结果" > </textarea > </div > </form > </body > <script > window .onload = () => { const inputEle = document .querySelector("#name" ); const resEle = document .querySelector("#res" ); inputEle.addEventListener("input" , function (event) { console .log(this .value); resEle.value += `\n${ this .value } ` }); } </script >
实现的效果如下:
即使我们想要执行输出逻辑,但是也不能接受这么高频率的输出,一个是造成了输出内容冗余,二是渲染强度高,不太划算。
新需求 假如,现在有这么一个新需求,要我们在 input 事件中加入新的逻辑:每隔一段时间后,都会执行一次回调函数中的逻辑。
这个需求是不是挺符合节流函数的使用场景的,那我们赶紧来实现一个吧。
实现节流 根据节流函数的定义:以固定的低频率执行代码逻辑,具体到我们上面的额需求来说,只要打开页面,不管你有没有输入,都会每隔几秒就执行一次保存数据的逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 window .onload = function ( ) { const resEle = document .querySelector("#res" ); function changeOutputVal (value ) { resEle.value += `\n${ value } ` ; } function throttle (fun, delay ) { let last, deferTimer return function (args ) { let that = this ; let _args = arguments ; let now = +new Date (); if (last && now < last + delay) { clearTimeout(deferTimer); deferTimer = setTimeout(function ( ) { last = now; fun.apply(that, _args); }, delay) } else { last = now; fun.apply(that, _args); } } } const outputRes = throttle(changeOutputVal, 2000 ); const inputEle = document .querySelector("#name" ); inputEle.addEventListener("input" , (eve) => { outputRes(eve.target.value); }); }
代码说明:
每一次事件被触发,都会判断间隔时间是否大于等于 delay,如果是,则执行输出逻辑;如果否,则清除原先的延时器,重新计算延时时间;
运行效果如下:
可以看到,在加入节流代码之后,输出事件不会每次 input 事件都触发,而是每隔 delay 时间触发一次。
~
~
代码比较粗糙,也比较基础,后面会逐步向着复杂的方向迭代,望各位看官海涵🙏
~
~
~ 本文完
学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!
大家好!我是〖编程三昧〗的作者 隐逸王 ,我的公众号是『编程三昧』,欢迎关注,希望大家多多指教!
知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!