vue +typescript (用的 vue-class-component) 怎么写节流和防抖函数

vue +typescript (用的 vue-class-component) 怎么写节流和防抖函数

阅读 3k
1 个回答

避免重复造轮子, 我之前手写过一次, 主要用于class样式的vue, 处理过this, 可以直接在方法中用this
P.S. 基于Vue2

/**
 * 节流函数, 若距离上一次执行该函数少于time, 将被延后至距离上一次执行time毫秒后执行
 * 不会重复执行
 * @param time 节流时间, 单位毫秒
 * @example
 * class Comp extends Vue {
 *
 *    @Throttle(1000)
 *    private fun() {
 *        console.log('run')
 *    }
 * }
 */
export function Throttle(time: number) {
  return function(
    target: Object,
    propertyKey: string | symbol,
    descriptor: TypedPropertyDescriptor<any>
  ): void {
    const rawValue = descriptor.value
    let _lastTime: number | null = null
    let _lastTimeId: number | null = null
    descriptor.value = function(this: any) {
      const args = arguments
      const now = +new Date()
      if (_lastTimeId) {
        clearTimeout(_lastTimeId)
        _lastTimeId = null
      }
      if (!_lastTime || now - _lastTime > time) {
        // 直接执行
        _lastTime = now
        rawValue.apply(this, args)
      } else {
        // 延迟执行
        _lastTimeId = window.setTimeout(() => {
          _lastTime = +new Date()
          rawValue.apply(this, args)
        }, now - _lastTime)
      }
    }
  }
}

/**
 * 防抖函数
 * 若最后执行, 每一次触发都, 都在time毫秒后执行, 若在time毫秒内再次调用, 将会再次推迟
 * 若首次执行, 则调用时立即触发, 若距离上一次执行少于time毫秒, 将跳过本次执行
 * @param time 防抖时长, 单位毫秒
 * @param lastExec 最后执行还是首次执行, 默认最后之星
 * @param processCallback 回调函数, 在抖动期间开始时传入true, 函数执行后(抖动结束后)传入false
 * @example
 * class Comp extends Vue {
 *
 *    @Debounce(1000)
 *    private fun() {
 *        console.log('run')
 *    }
 * }
 */
export function Debounce(
  time: number,
  lastExec = true,
  processCallback: ((val: boolean) => void) | string = () => {}
) {
  if (lastExec) {
    // 最后触发
    return function(
      target: Object,
      propertyKey: string | symbol,
      descriptor: TypedPropertyDescriptor<any>
    ): void {
      const rawValue = descriptor.value
      let _lastTimeId: number | null = null
      descriptor.value = function(this: any) {
        const args = arguments
        const processCB =
          typeof processCallback === 'string'
            ? ((this[processCallback] ?? Function.prototype) as Function)
            : processCallback
        processCB.call(this, true)
        if (_lastTimeId) {
          clearTimeout(_lastTimeId)
        }
        _lastTimeId = window.setTimeout(() => {
          processCB.call(this, false)
          rawValue.apply(this, args)
        }, time)
      }
    }
  } else {
    // 首先触发
    return function(
      target: Object,
      propertyKey: string | symbol,
      descriptor: TypedPropertyDescriptor<any>
    ): void {
      const rawValue = descriptor.value
      let _lastTime: number | null = null
      descriptor.value = function(this: any) {
        const now = +new Date()
        if (!_lastTime || now - _lastTime > time) {
          // 直接执行
          _lastTime = now
          rawValue.apply(this, arguments)
        }
      }
    }
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题