防抖节流 叁歲伎倆 2022-11-14 14:41 226阅读 0赞 ## 防抖(debounce) ## **从滚动条监听的例子说起** 先说一个常见的功能,很多网站会提供这么一个按钮:用于返回顶部。这个按钮只会在滚动到距离顶部一定位置之后才出现,那么我们现在抽象出这个功能需求-- **监听浏览器滚动事件,返回当前滚条与顶部的距离**,这个需求很简单,直接写: function showTop () { var scrollTop = document.body.scrollTop || document.documentElement.scrollTop; console.log('滚动条位置:' + scrollTop); } window.onscroll = showTop 但是,在运行的时候会发现存在一个问题:**这个函数的默认执行频率,太!高!了!**高到什么程度呢?以chrome为例,我们可以点击选中一个页面的滚动条,然后点击一次键盘的【向下方向键】,会发现函数执行了**8-9次**!然而实际上我们并不需要如此高频的反馈,毕竟浏览器的性能是有限的,不应该浪费在这里,所以接着讨论如何优化这种场景。 **所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。** 基于上述场景,首先提出第一种思路:**在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms**,然后: * 如果在200ms内没有再次触发滚动事件,那么就执行函数 * 如果在200ms内再次触发滚动事件,那么当前的计时取消,重新开始计时 效果:如果短时间内大量触发同一事件,只会执行一次函数。 实现:既然前面都提到了计时,那实现的关键就在于`setTimeout`这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现: /* * fn [function] 需要防抖的函数 * delay [number] 毫秒,防抖期限值 */ function debounce(fn,delay){ let timer = null //借助闭包 return function() { if(timer){ clearTimeout(timer) //进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时 timer = setTimeout(fn,delay) }else{ timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时,那么就开始一个计时 } } } 此时会发现,必须在停止滚动1秒以后,才会打印出滚动条位置。 到这里,已经把**防抖**实现了,现在给出定义: * 对于**短时间内连续触发**的事件(上面的滚动事件),**防抖的含义就是让某个时间期限(如上面的1000毫秒)内,事件处理函数只执行一次。** 像防抖还是很容易想到的,大概意思就是延时处理,然后如果在这段延时内又触发了事件,则重新开始延时。 // 简单示例 window.addEventListener('resize',function(e){ var t; return function(){ if(t) clearTimeout(t); t = setTimeout(function(){ // do something... },500); } }()); ## 节流(throttle) ## **让一个函数无法在很短的时间间隔内连续调用,当上一次函数执行后过了规定的时间间隔,才能进行下一次该函数的调用。** 为什么要函数节流?以下场景往往由于事件频繁被触发,因而频繁执行DOM操作、资源加载等重行为,导致UI停顿甚至浏览器崩溃。 * window对象的resize、scroll事件 * 拖拽时的mousemove事件 * 射击游戏中的mousedown、keydown事件 * 文字输入、自动完成的keyup事件 不断滚动页面,页面使用上面的防抖方案来处理问题的结果是:如果在限定时间段内,不断触发滚动事件(比如某个用户闲着无聊,按住滚动不断的拖来拖去),只要不停止触发,理论上就永远不会输出当前距离顶部的距离。**但是如果要实现:即使用户不断拖动滚动条,也能在某个时间间隔之后给出反馈呢?** 其实很简单:我们可以设计一种**类似控制阀门一样定期开放的函数,也就是让函数执行一次后,在某个时间段内暂时失效,过了这段时间后再重新激活**(类似于技能冷却时间)。 效果:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。 实现:借助`setTimeout`来做一个简单的实现,加上一个状态位`valid`来表示当前函数是否处于工作状态: function throttle(fn,delay){ let valid = true return function() { if(!valid){ //休息时间 暂不接客 return false } // 工作时间,执行函数并且在间隔期内把状态位设为无效 valid = false setTimeout(() => { fn() valid = true; }, delay) } } /* 请注意,节流函数并不止上面这种实现方案, 例如可以完全不借助setTimeout,可以把状态位换成时间戳,然后利用时间戳差值是否大于指定间隔时间来做判定。 也可以直接将setTimeout的返回的标记当做判断条件-判断当前定时器是否存在,如果存在表示还在冷却,并且在执行fn之后消除定时器表示激活,原理都一样 */ // 以下照旧 function showTop () { var scrollTop = document.body.scrollTop || document.documentElement.scrollTop; console.log('滚动条位置:' + scrollTop); } window.onscroll = throttle(showTop,1000) 运行以上代码的结果是: * 如果一直拖着滚动条进行滚动,那么会以1s的时间间隔,持续输出当前位置和顶部的距离 ## 应用场景 ## 1. 搜索框input事件,例如要支持输入实时搜索可以使用节流方案(间隔一段时间就必须查询相关内容),或者实现输入间隔大于某个值(如500ms),就当做用户输入完成,然后开始搜索,具体使用哪种方案要看业务需求。 2. 页面resize事件,常见于需要做页面适配的时候。需要根据最终呈现的页面情况进行dom渲染(这种情形一般是使用防抖,因为只需要判断最后一次的变化情况) 3. 一般,滚动加载无限页面的时候可以应用节流 经典原文链接:[https://segmentfault.com/a/1190000018428170][https_segmentfault.com_a_1190000018428170] [https_segmentfault.com_a_1190000018428170]: https://segmentfault.com/a/1190000018428170
相关 防抖、节流 原生js中 简单实现: function a() { console.log('触发了!!!') } // 节流: 规定的时间内 我会带着你远行/ 2023年07月12日 03:34/ 0 赞/ 40 阅读
相关 防抖节流 故心故心故心故心小故冲啊 -------------------- 文章目录 防抖 节流 总结 -------------------- 防抖 r囧r小猫/ 2023年01月12日 11:36/ 0 赞/ 161 阅读
相关 javascript 防抖、节流 一、防抖 > 防抖——触发高频事件后 n 秒后函数只会执行一次,如果 n 秒内高频事件再 次被触发,则重新计算时间; 1. 原理 短时间内多次触发同一事件 左手的ㄟ右手/ 2022年12月18日 15:56/ 0 赞/ 163 阅读
相关 防抖节流 防抖(debounce) 从滚动条监听的例子说起 先说一个常见的功能,很多网站会提供这么一个按钮:用于返回顶部。这个按钮只会在滚动到距离顶部一定位置之后才出现,那么我们 叁歲伎倆/ 2022年11月14日 14:41/ 0 赞/ 227 阅读
相关 防抖、节流 防抖:只要用户触发事件,清除定时器,重新开始记时,避免全局污染,选择使用闭包实现效果。 节流:让用户在一段时间之内,只能执行一次。 判断当前的tag,tag是true允许执 ╰半橙微兮°/ 2022年09月14日 09:23/ 0 赞/ 220 阅读
相关 防抖和节流 1. 防抖 触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间 \ 思路:每次触发事件时都取消之前的延时调用方法 function 朱雀/ 2022年03月18日 01:44/ 0 赞/ 315 阅读
相关 节流、防抖 节流和防抖主要处理事件处理函数高频调用,减少浏览器负担 节流:尽量减少触发次数,mint-ui上封装了一个方法 <script> var t 向右看齐/ 2022年01月30日 00:39/ 0 赞/ 351 阅读
相关 防抖和节流 防抖和节流 一、什么是防抖 二、防抖使用场景 1.输入框是按键触发请求时 三、什么是节流 四、节流的使用场景 1.鼠标连续 快来打我*/ 2021年09月07日 06:13/ 0 赞/ 495 阅读
相关 防抖节流 通过闭包返回的函数来进行操作,使得变量一直存在 防抖: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shado 不念不忘少年蓝@/ 2021年07月24日 23:49/ 0 赞/ 465 阅读
相关 防抖节流 vue代码 防抖 // timer用于储存定时器 delayed(){ // 检测定时器 if(this.timer){ 妖狐艹你老母/ 2021年07月24日 18:39/ 0 赞/ 484 阅读
还没有评论,来说两句吧...