前端节流、防抖

参考文章1
参考文章2

节流和防抖是什么

节流和防抖是优化高频率执行代码的一种方式,像项目中会涉及到的监听浏览器的resize、scroll、keypress、mousemove等事件在触发时,会不断地调用绑定在事件上的回调函数,但实际上这么频繁的调用会降低前端性能,故我们可以对这类事件进行调用次数的限制,通过节流(throttle)防抖(debounce) 的方式来减少调用频率。

  • 相同点
    目的都是降低回调执行频率,节省性能资源,都可以通过定时器实现,

  • 不同点
    节流是指设定一个时间周期,在这个时间周期内如果连续执行某操作,只有一次操作能生效,受时间周期限制
    防抖同样会设定一个时间周期,但操作生效的时间点不受时间周期的限制,连续执行某操作,只有一次操作生效,即使操作生效的时间点超出时间周期范围


下面示例会用到的公共代码片段

<button>点我</button>
function a(n) {
    console.log(n)
}

一、节流 (throttle)

固定周期内,即使多次触发事件,也只执行一次动作;周期结束后,再次触发事件,开始新的周期。

根据事件触发的时间点可分为延迟节流前缘节流

1.延迟节流 指周期结束后执行动作

在这里插入图片描述

定时器写法

简易初版

let flag = true;
const throttling = (fn,param delay) => {
    if (flag) {
        flag = false;
        setTimeout(() => {
        	fn(...param);
            flag = true;
        }, delay)
    }
}
document.getElementsByTagName("button")[0].addEventListener("click", () => {
    throttling(a,[2] 3000)
})

使用闭包优化后

function throttling(fn, delay) {
    // timer的作用域在外层函数作用域
    let timer = null;
    return (n) => {
        if (!timer) {
            timer = setTimeout(() => {
                fn.call(this, n);
                clearTimeout(timer)
                timer = null;
            }, delay)
        }
    }
}
const b = throttling(a,3000);
document.getElementsByTagName("button")[0].addEventListener("click", () => {
    b(2)
})

2.前缘节流 指执行动作后再开始周期

在这里插入图片描述

定时器写法
function throttling(fn, delay) {
    // timer的作用域在外层函数作用域
    let timer = null;
    return (n) => {
        if (!timer) {
            fn.call(this, n);
            timer = setTimeout(() => {
                clearTimeout(timer)
                timer = null;
            }, delay)
        }
    }
}
const b = throttling(a, 3000,true);
document.getElementsByTagName("button")[0].addEventListener("click", () => {
    b(2)
})
时间戳写法
function throttling(fn, delay) {
    // timer的作用域在外层函数作用域
    let oldtime = 0;
    return (n) => {
        let newtime = Date.now();
        if(newtime - oldtime > delay){
            fn.call(this,n);
            oldtime = newtime;
        }
    }
}

3.延迟节流和前缘节流统一处理

形参immediate控制周期开始/结束时执行动作

function throttling(fn, delay, immediate = false) {
    // timer的作用域在外层函数作用域
    let timer = null;
    return (n) => {
        if (!timer) {
            immediate && fn.call(this, n);
            timer = setTimeout(() => {
                !immediate && fn.call(this, n);
                clearTimeout(timer)
                timer = null;
            }, delay)
        }
    }
}
const b = throttling(a, 3000,true);
document.getElementsByTagName("button")[0].addEventListener("click", () => {
    b(2)
})

二、防抖 (debounce)

同样,根据事件触发的时间点可分为分为延迟防抖前缘防抖

1.延迟防抖

当事件触发时,设定一个周期延迟执行动作,若期间又被触发,则重新设定周期,直到周期结束,执行动作
在这里插入图片描述

 function debounce(fn, delay) {
  // timer的作用域在外层函数作用域
   let timer = null;
   return (n) => {
     timer && clearInterval(timer);
     timer = setTimeout(() => {
       fn.call(this, n);
       clearTimeout(timer);
       timer = null;
     }, delay);
   };
 }
 const b = debounce(a, 3000);
 document.getElementsByTagName("button")[0].addEventListener("click", () => {
   b(2);
 });

2.前缘防抖

执行动作在前,然后设定周期,周期内有事件被触发,不执行动作,且周期重新设定
在这里插入图片描述

 function debounce(fn, delay) {
  // timer的作用域在外层函数作用域
   let timer = null;
   return (n) => {
     !timer && fn.call(this, n);
     timer && clearInterval(timer);
     timer = setTimeout(() => {
       clearTimeout(timer);
       timer = null;
     }, delay);
   };
 }
 const b = debounce(a, 3000,true);
 document.getElementsByTagName("button")[0].addEventListener("click", () => {
  b(2);
 });

3.延迟防抖和前缘防抖统一处理

形参immediate控制周期开始/结束时执行动作

 function debounce(fn, delay, immediate = false) {
  // timer的作用域在外层函数作用域
   let timer = null;
   return (n) => {
     immediate && !timer && fn.call(this, n);
     timer && clearInterval(timer);
     timer = setTimeout(() => {
       !immediate && fn.call(this, n);
       clearTimeout(timer);
       timer = null;
     }, delay);
   };
 }
 const b = debounce(a, 3000,true);
 document.getElementsByTagName("button")[0].addEventListener("click", () => {
  b(2);
 });

应用场景

1.防抖

input输入框,只需用户最后一次输入完,显示输入结果,或检测正确
浏览器窗口resize事件,在用户进行一连串调整窗口的动作后,再计算需要的信息,防止重复渲染

2.节流

监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断
鼠标点击事件不断触发,单位时间内只执行一次

vue自定义指令

前缘节流

<el-button type="text" v-throttle="{ fn: onAddRecord, param: [item], time: 5*1000 }">按我</el-button>
-------------------
Vue.directive('throttle', throttle)
--------------------
/**
 * 节流
 */
export const throttle = {
  bind(el, binding, vnode){
    let {fn, param = [], event = "click", time = 1000} = binding.value;
    let timer = null;
    el.addEventListener(event, () => {
      if(!timer){
        fn(...param);
        timer = setTimeout(()=>{
          clearTimeout(timer);
          timer = null;
        },time)
      }
    })
  }

前缘防抖

<div v-debounce="() => { checkBindRole(roleMsg); } ">确认</div>
--------------------
Vue.directive("debounce", {
  inserted: function(el, binding, vnode) {
    let {fn, param = [], event = "click", time = 1000} = binding.value;
    let timer = null;
    el.addEventListener(event, () => {
      timer &&  clearTimeout(timer);
      //binding.value()即调用传进来的方法
     !timer && fn(...param);
      timer = setTimeout(() => {
        timer = null;
      }, time);
    });
  },
});
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前端防抖节流的使用场景很多。其中一种常见的场景是在用户输入搜索框时进行搜索提示。当用户快速输入时,如果每次输入都立即触发搜索请求,会造成过多的请求并降低性能。这时可以使用防抖来延迟执行搜索请求,只当用户停止输入一段时间后才触发搜索请求,避免不必要的请求。 另一个使用场景是在页面滚动时进行懒加载。当用户滚动页面时,如果每次滚动都立即加载图片或数据,会造成页面卡顿。通过使用节流,可以控制在一定时间内只触发一次加载,提高页面的流畅度。 此外,防抖节流还可以应用于按钮点击事件,防止用户频繁点击按钮导致重复提交或执行多次操作。通过设置适当的延迟时间,可以确保在用户点击按钮后只执行一次操作。 总之,前端防抖节流的使用场景包括搜索提示、懒加载和按钮点击事件等,通过延迟执行或控制触发频率,可以提升用户体验和页面性能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [前端节流防抖的实景应用](https://blog.csdn.net/qq_52022825/article/details/125057737)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [防抖节流的封装函数与使用详解](https://download.csdn.net/download/weixin_38695061/14888196)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值