vue采用装饰器实现节流、防抖功能

167 阅读1分钟

概念: 节流:当持续触发事件时,保证一定时间段内只调用一次事件处理函数。
防抖:当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。 应用场景: 节流:监听浏览器滚动、多次点击情况下可以采用该功能。

参考地址:blog.csdn.net/stupid_musc…


// 防抖
export function PromiseDebounce(time = 200, delayTime = 250) {
    return function (
      target: any,
      propertyKey: string,
      descriptor: PropertyDescriptor
    ) {
      const original = descriptor.value;
      const debounceFn = function () {
        let timer = null;
        const execFn = function (...args: any) {
          if (timer) clearTimeout(timer);
          timer = setTimeout(async () => {
            const data = await Promise.all([
              original.call(this, ...args),
              new Promise((resolve) => {
                setTimeout(resolve, time);
              }),
            ]);
            return data[0];
          }, time);
        };
        return execFn;
      };
      descriptor.value = debounceFn();
      return descriptor;
    }
}

/**
 * 网络请求节流装饰器,对网络请求进行锁操作,网络请求结束之后释放
 * @param time 等网络请求结束和设置时间完成之后释放节流
 * @param delayTime 延迟被装饰方法的触发时间
 */
export function PromiseThrottle(time = 200, delayTime = 500) {
    return function (
      target: any,
      propertyKey: string,
      descriptor: PropertyDescriptor
    ) {
      const original = descriptor.value;
      const throttleFn = function () {
        let status = '';
        const execFn = async function (...args: any) {
          if (status === 'ing') {
            return;
          }
          status = 'ing';
          try {
            const data = await Promise.all([
              original.call(this, ...args),
              new Promise((resolve) => {
                setTimeout(resolve, time);
              }),
            ]);
            return data[0];
          } finally {
            setTimeout(() => {
              status = '';
            }, delayTime);
          }
        };
        return execFn;
      };
      descriptor.value = throttleFn();
      return descriptor;
    };
  }

以下示例使用在多次点击按钮的情况下,故采用反抖的方式对方法进行处理。

未采用装饰器之前的写法

import { Options, Vue } from 'vue-class-component'
 
export default class demo extends Vue {
    data(){
        return {
            clickTime: new Date().getTime()
        }
    }
    save(){
        let delta = Date.now() - this.clickTime //计算两次点击时间差
        this.clickTime = Date.now()
        if (delta > 0 && delta <= 250) {
          //双击事件
            return
        }
        console.log("save")
    }
}

采用装饰器之后的写法

import { Options, Vue } from 'vue-class-component'
import { PromiseThrottle } from "./common.ts"
export default class demo extends Vue {
    @PromiseThrottle(500)
    save(){
        console.log("save")
    }