js,ts防抖函数

4,108 阅读2分钟

原理: 存在一定的情况高频触发时间,如滚动,unblur ,快速点击等情况,不想频繁的触发相应的事件,则需要防抖函数来控制事件触发结束后来进行相应的回调 仅执行一次 其中使用了闭包来进行存储timer值,若不了解闭包可以看闭包详解 juejin.cn/post/684490…

简单的防抖函数

// func 回调函数  delay 延迟ms
export default function(func,delay){
    //因使用es6模块语法  此时this指向undefined
    let timer
    return function(){
        //此时的this指向调用者 window或者vue实例
        let that = this
        clearTimeout(timer)
        timer = setTimeout(()=>{
            func.apply(that)        
        })            
    }
}

稍微复杂一点的防抖函数

    // func 回调函数 delay 延迟ms immediate 是否立即执行
export default function(func, delay=1000, immediate = false){
    let timer
    console.log(this)
    return function(...args){
        let that = this
        if(immediate){
            func.apply(that,args)
            immediate = false
            return
        }
        clearTimeout(timer)
        timer = setTimeout(()=>{
            func.apply(that,args)
        },delay)
    }
}

ts版本的防抖函数

/**
 * 防抖函数
 * @param func 执行函数
 * @param delay 延迟时间 ms
 * @param immediate 是否立即执行
 */
export default function (func: Function, delay: number, immediate: boolean = false): Function {
  let timer: number | undefined

  return function (this: unknown, ...args: any[]) {
    let that = this
    if (immediate) {
      func.apply(that, args) // 确保引用函数的指向正确,并且函数的参数也不变
      immediate = false
      return
    }
    clearTimeout(timer)
    timer = setTimeout(() => {
      func.apply(that, args)
    }, delay)
  }
}

防抖节流一体函数

export default function (func,delay,options){
    let timer
    let defaultOption = {
        debounce:true,
        trailing: true,
        leading: false,
    }
}

vue中使用防抖函数

<template>
    <div>
      <h3>This is demo1</h3>
      <p>
        test debounce
        <button type="button" @click="noDeounceFunc($event,'点击noDebounce')">noDeounce</button>
        <button type="button" @click="debounceFunc($event,'点击Debonce')">debounce</button>
      </p>
    </div>
  </template>
  
  <script>
  import debounce from "../utils/debounce.js";
  export default {
    methods: {
      debounceFunc:debounce((event,msg)=>{
        console.log(msg);
      }, 2000),

      noDeounceFunc:(event,msg)=> {
        console.log(msg);
      }
    },
  };
  </script>

防抖节流通用函数 leading为true时,每隔delay触发一次时间。否则与防抖效果相同

export function debounce(func,delay,option){
    return base(func,delay,Object.assign({},{
        debounce:true,
    },option))
}

export function throttle(func,delay,option){
    return base(func,delay,Object.assign({},,{leading:true,debounce:false}option))
}

function base (func,delay = 2000,option){
    let timer
    let lastExecTime = 0
    let defaultOption = {
        leading: false,
        debounce: false,
        trailing: true,
    }
    const {leading, debounce, trailing} = Object.assign({},defaultOption,option);
    return function(...args){
        const that = this
        const previous = +new Date() - lastExecTime
        let isNotLeading = true
        function exec(){
            lastExecTime = +new Date()
            func.apply(that,args)
        }

        function clear(){
            timer = null
            exec()
        }

        if (leading && ((!debounce && previous > delay) || (debounce && timer === null))) {
            exec()
            isNotLeading = false
          }

        if(timer){
            clearTimeout(timer)
        }

        if(trailing && isNotLeading){
            console.log(isNotLeading)
            timer = setTimeout(debounce? clear: exec,delay)
        }
    }
}