找回密码
 立即注册
首页 业界区 业界 防抖和节流

防抖和节流

闻人莹华 2025-6-6 15:48:17
1. 防抖,回城-执行完成区间计时的那一次

触发事件时开始计时,计时结束后执行事件处理。当计时未结束再次触发事件,则清除计时器并重新计时。
思路:利用闭包,保存回调函数的计时器。判断计时器是否存在,是-清除原计时器。在计时器内调用事件处理函数。
注意:这里要搞清楚返回的匿名函数才是绑定的点击事件,而非 debounce 函数。匿名函数可以访问父函数 debounce 声明的 timer,每次调用匿名函数时,timer 的数据得到保留。
  1. <button>防抖-计时器</button>
  2. <button clss="notTimer">防抖-非计时器</button>
复制代码
  1. // 使用计时器
  2. let btn = document.querySelector('button');
  3. btn.addEventListener('click', debounce(handler));
  4. // 事件处理函数
  5. function handler(e) {
  6.   console.log(e);                        //未传入参数时为undefine | 传参后:PointerEvent 
  7.   console.log(this);            //未修改时为window | 修改this后:<button>防抖-计时器</button>
  8. }
  9. // 防抖函数
  10. function debounce(fn) {
  11.   let timer;
  12.   // 新的事件会刷新旧的事件,直到最后一件事等待1s后执行
  13.   return function (e) {                        // 返回作为回调事件
  14.     let _this = this;                // 注意:计时器的this只能指向window,用箭头函数可继承父业(es6)
  15.     if (timer) clearTimeout(timer);
  16.     timer = setTimeout(function () {
  17.       // 传入函数调用,提高可复用性
  18.       fn.call(_this, e); //!修改this,得去记,得去用啊宝宝:call/bind/apply
  19.     }, 1000)
  20.   }
  21. }
复制代码
也可以用节流的计时方式。
  1. // 不使用计时器
  2. let btn1 = document.querySelector('.notTimer');
  3. btn1.addEventListener('click', (function () {
  4.     let currTime = Date.now();
  5.     return function (e) {
  6.       let nowTime = Date.now();
  7.       if (nowTime - currTime < 3000) { // 时效内点击,刷新计时器
  8.           currTime = nowTime;
  9.           return;
  10.       }
  11.       // 调用处理函数
  12.       console.log(e)
  13.       console.log(this)
  14.       currTime = nowTime; // 处理完毕,刷新计时器
  15.     }
  16. })())<br>
复制代码
 
2. 节流,cd-区间内只执行第一次,禁止执行第二次

触发事件后立即执行事件处理,并开始计时,计时结束前,触发事情不执行事件处理。(合理来说应该是直到第一个执行完毕,可以设置标记,执行完修改标记,作为锁)
思路:记录第一次执行调用的时间戳,超时才能执行下一次调用,并重置起始时间。
  1. window.addEventListener('scroll', throttle(handlerScroll, 1000));
  2. // 事件处理函数
  3. function handlerScroll(e) {
  4.   console.log(e);
  5.   console.log(this);
  6. }
  7. // 节流函数
  8. function throttle(fn, delay) {
  9.   let prevTime = Date.now();
  10.   return function (e) {
  11.     let nowTime = Date.now();
  12.     if (nowTime - prevTime > delay) { // 区间计时结束,执行处理,并刷新起始时间
  13.       fn.apply(this, e);
  14.       prevTime = Date.now();
  15.     }
  16.   }
  17. }<br>
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册