Typescript封装防抖和节流函数

27 篇文章 0 订阅
24 篇文章 0 订阅
防抖函数

在规定时间内重复执行同一个函数,但是只生效一次函数的行为。比如由于网络延迟,用户在一定时间内会重复点击某一个按钮,然而不断的执行按钮上的事件。若该事件是网络请求,则会给服务器不断造成压力,这是我们不愿看到的。

节流函数

在规定时间内重复执行同一个函数,但是按照一定的时间段生效函数的行为。和防抖函数非常相似。例如在支付回调后我们要确认支付的状态,可以手动检查+自动检查的情况下,我们使用节流函数是一个不错的选择。

相对于使用JavaScript封装这两个函数主要区别在于this的指向问题。使用JavaScript封装我们大可以使用apply在函数中指向,但是对于Typescript中的this单独在函数中使用却是大大受限制的。所以在typescript中我们使用class来解决这一问题。

代码演示:

// 防抖(ts)
class Debounced {
  /**
   * @param func 需要包装的函数
   * @param delay 延迟时间,单位ms
   * @param immediate 是否默认执行一次(第一次不延迟)
   */
  public use = (func: Function, delay: number, immediate: boolean = false): Function => {
    let timer: number | undefined
    return ( ...args: any) => {
      if (immediate) {
        func.apply(this, args) // 确保引用函数的指向正确,并且函数的参数也不变
        immediate = false
        return
      }
      clearTimeout(timer)
      timer = setTimeout(() => {
        func.apply(this, args)
      }, delay)
    }
  }
}

// 节流(ts)
export class Throttle {
  private timer: number | undefined
  private stop: boolean = false
  private death: boolean = false
  /**
   * @param func 需要包装的函数
   * @param delay 延迟时间,单位ms
   * @param immediate 是否默认执行一次(第一次不延迟)
   */
  public use (func: Function, delay: number, immediate: boolean = false): Function {
    let flag = true
    const self = this
    return (...args: any) => {
      if (this.death) {
        func.apply(this, args)
        return
      }
      if (this.stop) {
        func.apply(this, args)
        return
      }
      if (immediate) {
        func.apply(this, args)
        immediate = false
        return
      }
      if (!flag) {
        return
      }
      flag = false
      self.timer = setTimeout(() => {
        func.apply(this, args)
        flag = true
      }, delay)
    }
  }

  // 销毁
  public destroy() {
    this.death = true
    this.stop = true
    if (!!this.timer) {
      clearTimeout(this.timer)
      this.timer = undefined
    }
  }
  // 开启
  public open() {
    if (!this.death) {
      this.stop = false
    }
  }
  // 关闭
  public close() {
    this.stop = true
  }
}

使用:

<template>
  <div id="debounced-test">
    <v-button @click="handelClickByDebounced">防抖</v-button>
    <v-button @click="handelClickByThrottle" type="success">节流</v-button>
    <v-button @click="changeStopThrottle(throttle.stop)" type="warning">
      {{ throttle.stop ? '开启' : '关闭' }}节流
    </v-button>
    <v-button @click="destroyThrottle" type="danger">销毁节流函数</v-button>
  </div>
</template>

<script lang="ts">
import { Debounced, Throttle } from '@/utils'
import { Vue, Component } from 'vue-property-decorator'

@Component
export default class DebouncedTest extends Vue {
  private count: number = 1
  private debouncedUse: Function = new Debounced().use(this.request, 1000)
  private throttle = new Throttle()
  private throttleUse: Function = this.throttle.use(this.request, 1000)

  private request(params: any) {
    console.log('this的指向', this);
    console.log('参数', params);
    console.log(this.count++)
  }
  // 防抖调用
  private handelClickByDebounced() {
    this.debouncedUse(123)
  }
  // 节流调用
  private handelClickByThrottle() {
    this.throttleUse('截流函数')
  }
  // 停止 | 开启节流函数
  private changeStopThrottle(action: boolean) {
    action ? this.throttle.open() : this.throttle.close()
  }
  // 销毁节流函数
  private destroyThrottle() {
    this.throttle.destroy()
  }
}
</script>

演示
演示

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值