防抖节流封装

1,568 阅读2分钟

概念

由于目前做的项目登录这块需要做单点登录,但是频繁点击登录按钮,就会出现刚登录上去提示“您的账号在别处登录”,然后被测试提了一个bug。怎么修复了?可以在登录时加节流,由此想着可以封装一下公共的防抖节流的方法。

防抖和节流其实我们在工作中经常会遇到,在这里简单对其概念做下简单描述:

  • 防抖: 触发事件在一定时间内只执行一次,如果这段时间内又触发了,则会重新计算函数执行时间
  • 节流:连续触发事件但在一定时间内只执行一次的函数

知道了概念以后,我们可以简单封装一下我们自己的防抖节流函数

手写防抖

 知道了基本概念,手动实现一下防抖函数

/**
* 防抖的函数
* @param {*} func 要执行的函数
* @param {*} await  等待时间
* @param {*} immidate   是否立即执行, 默认falseß
*/
function debounce(func, await, immidate = false){ 
   let timer =  null
   let debounce;
   debounce = function() {
       //this指向问题
       let context = this;
       //拿到参数
       let args = [...arguments];
       clearTimeout(timer);
       if(immidate){
           let callNow = !timer;
           timer = setTimeout(()=>{
               timer = null;
           }, await)

           //立即执行
           callNow && func.apply(context, args);
       } else {
           timer = setTimeout(()=>{
               func.apply(context, args);
           }, await)
       }
   }

   //取消防抖函数
   debounce.cancal = ()=>{
       clearTimeout(timer);
       timer = null;
   }
   return debounce
}

手写节流

/**
* 节流函数
* @param {*} func    要执行的函数
* @param {*} await    每隔多长时间执行
*/
function throttle(func, await){
    let context, args;
    let previous = 0;   //之前的时间戳
    return function(){
        ([context, args] = [this, arguments])
        let now = new Date().valueOf();  //获取当前的时间戳
        if(now-previous>await){
            func.apply(context, args);
            old = now;
        }
    }
}

vue指令板

在实际情况中,防抖和节流的应用场景是非常多的。在vue项目中,我们可以将写好的方法挂载到vue原型上,这样的话整个项目无需再引入,可以全局使用。除此之外,我们还可以注册一个全局的指令,利用指令实现防抖节流的作用。

自定义指令的钩子函数和使用方法参考官网: 自定义指令官网地址

Vue.directive('throttle', {
   inserted: function(el, binding) {
      let timer;
       el.addEventListener("click", () => {
         if (timer) {
           clearTimeout(timer);
         }
         timer = setTimeout(() => {
           binding.value();
         }, 1000);
       });
     }
})