摘要:文件为函数要传入的参数返回事件处理函数添加事件监听节流函数一般用于事件的情况较多,因为这些事件的触发是连续性的,需要在一个时间间隔内只触发一次。
阅读原文
在前端开发当中我们经常会绑定一些事件触发的某些程序执行,有时这些事件会连续触发,如浏览器窗口 scroll、resize,输入框的 keyup、input,以及 click 事件在连续点击时连续发送请求等等,这些情况有些会严重影响前端性能,有些会增加服务器压力,使用户体验大打折扣,而函数节流和防抖就是为了解决这样的问题。
函数节流 throtter函数节流:当持续发生事件时,保证在一个固定的时间间隔只执行一次真正的事件处理程序,通俗的说就像 “节流” 的名字一样,打开水龙头时要秉承勤俭节约的原则,把阀门关小,最好是达到在固定间隔内水一滴一滴的往下流。
1、节流函数的时序图从图中可以看出,连续触发事件时,真正执行事件处理程序的间隔是固定的,多次触发,也只会在某一个时间间隔内触发一次,由于事件处理函数内部执行逻辑各不相同,我们就封装一版可通用的节流函数。
2、节流函数的封装// 文件:throtter.js // 节流函数 const throtter = (func, delay = 60) => { // 锁的标识 let lock = false; // 返回一个事件处理函数 return (...args) => { // 如果 lock 为 true 则跳出 if (lock) return; // 执行函数并更改锁的状态 func(...args); lock = true; // 添加定时器,在到达时间间隔时重置锁的状态 setTimeout(() => lock = false, delay); } }
throtter 函数有两个参数,第一个参数为在事件触发时真正要执行的函数,第二个参数为定义的间隔时间,在函数执行时定义了 lock 的初始值,通过闭包返回一个函数作为事件处理函数,在返回的函数内部判断 lock 状态并确定执行真正的函数 func 还是跳出,每次执行 func 后会更改 lock 状态,通过定时器在规定的时间间隔内重置 lock,这就是函数节流的原理。
3、验证节流函数// 文件:throtter-test.js // 使用节流函数 document.addEventListener("scroll", throtter(console.log));
上面我们给 document 对象添加了滚动事件,并不断的打印事件对象,事件处理函数的默认参数为事件对象,从执行效果应该可以看出,平均每 60ms 才会触发一次事件,达到了优化性能的目的,如果想让真正执行的函数 func 传入更多的参数,只需如下处理。
// 文件:throtter-test.js // a b 为函数要传入的参数 let a = 1, b = 2; // 返回事件处理函数 const func = throtter(console.log); // 添加事件监听 document.addEventListener("scroll", e => func(e, a, b));
节流函数一般用于 scroll、resize 事件的情况较多,因为这些事件的触发是连续性的,需要在一个时间间隔内只触发一次。
函数防抖 debounce函数防抖:当持续发生事件时,事件只在上一次触发后的一段时间内没再触发事件,才会真正的执行事件处理逻辑,如果每两次触发的间隔小于这个时间,则不执行事件逻辑。
1、防抖函数的时序图从图中可以看出,连续触发事件时并没有执行事件处理函数,只有在某一阶段连续触发后的最后一次才执行,也就是上一次触发的时间间隔要大于设定值才执行,同样的,事件处理函数内部执行逻辑各不相同,我们就封装一版可通用的防抖函数。
2、防抖函数的封装// 文件:debounce.js // 防抖函数 const dobounce = (func, delay = 300, timer = null) => { return (...args) => { // 清除定时器 clearInterval(timer); // 在定时器到时后执行事件处理函数 timer = setTimeout(() => func(...args), delay); } }
dobounce 函数有三个参数,第一个参数为在事件触发时真正要执行的函数,第二个参数为执行事件的延迟时间,第三个参数为定时器 ID 的初始值,执行 dobounce 通过闭包返回了事件处理函数,在处理函数内部先清除定时器,然后定义定时器并将 ID 赋值给 timer,如果事件连续触发,则会不断的清除定时器,直到有一次触发间隔超过了设定延时时间 delay,才会真正执行 func。
3、验证防抖函数函数防抖
// 文件:debounce-test.js // 使用防抖函数 let ipt = document.querySelector("#ipt"); // 添加事件监听 ipt.addEventListener("keyup", debounce(console.log));
上面的功能跟 throtter 类似,真正执行事件处理函数时打印事件对象,通过验证,连续输入触发 keyup 事件,上一次触发和下一次触发间隔时间必须大于 300ms 才会执行打印事件对象的逻辑,如果想传入多个参数套路相同。
// 文件:debounce-test.js // 获取 dom 元素 let ipt = document.querySelector("#ipt"); // a b 为函数要传入的参数 let a = 1, b = 2; // 返回事件处理函数 const func = debounce(console.log); // 添加事件监听 ipt.addEventListener("keyup", e => func(e, a, b));
防抖函数一般用于输入框事件,常用场景就是搜索或查询,如果不使用防抖会连续发送请求,增加服务器的压力,使用防抖后,会在用户输入要查询的关键词后才发送请求,这也更符合用户的习惯,例如百度搜索,就是这样实现的。
总结“节流” 和 “防抖” 是前端在项目中经常使用的优化手段,代码虽然不多,但是确是前端面试 “出镜率” 非常高的知识点,从而能看出它们的重要性,所以建议前端同学们一定要知道,并能手写,这是 “一箭双雕” 的事,可以用来通过面试,也可以因为工作中遇到直接就写而提高工作效率。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/98272.html
摘要:主要实现在于通过异步操作的事件间隔,对于前后两次调用方法打时间进行比较,用清空定时器的操作实现多余调用操作的舍弃。 废话不多说,直奔主题。 什么是throttle和debounce? 这两个方法的主要目的多是用于性能优化。最常见的应用尝尽就是在通过监听resize、scroll、mouseover等事件时候的性能消耗。拿scroll来说,没有处理时滑动一次滚动条scroll事件会触发多...
阅读 2891·2021-11-23 09:51
阅读 3142·2021-11-12 10:36
阅读 3169·2021-09-27 13:37
阅读 3139·2021-08-17 10:15
阅读 2571·2019-08-30 15:55
阅读 2714·2019-08-30 13:07
阅读 777·2019-08-29 16:32
阅读 2627·2019-08-26 12:00