Vue中按钮自定义防抖指令

161 阅读1分钟

背景

项目中多处出现重复提交调用接口,导致数据库存入多条相同数据

vue3

/**
 * example
 * params内可加自定义参数
 * <button v-debounce="{callback: test, params: {time: 0}}">防抖点击</button>
 * 接收参数
 * const test = (params) => {
 *   const { time } = params
 *   console.log('执行')
 * }
 *
 * @param binding.value.callback 回调函数
 * @param binding.value.params 回调函数参数
 * @param binding.value.delay 延迟时间
 */

export default {
  mounted(el: HTMLElement, binding: { value: { callback: Function; params?: any; delay?: number } }) {
    let timer: ReturnType<typeof setTimeout> | null = null;

    el.addEventListener('click', (e: Event) => {
      e.preventDefault();
      // 阻止冒泡
      e.stopPropagation();

      if (timer) clearTimeout(timer);

      let delay = binding.value?.delay || 500;

      timer = setTimeout(() => {
        const { callback, params } = binding.value;

        if (!callback || typeof callback !== 'function') {
          throw new Error('callback is not a function');
        }

        callback(params ? params : e);
        timer = null;
      }, delay);
    });
  }
}

这是vue2,不建议使用

首先书写一个指令方法

/**
 * @debounce
 * 按钮v-debounce防抖
 */
export default {
    /** bind */
    bind(el: any, binding: any, vnode: any) {
        let wait = binding.value; // 防抖时间
        if (!wait) {
            // 默认时间2s
            wait = 2000;
        }

        let timer: any = null;
        el.addEventListener(
            'click',
            (event: any) => {
		if (!timer) {
                    timer = setTimeout(() => {
			timer = null;
                    }, wait);
		} else {
                    clearTimeout(timer);
                    timer = setTimeout(() => {
                    timer = null;
		}, wait);
                    // eslint-disable-next-line no-unused-expressions
                    event && event.stopImmediatePropagation();
                }
            },
            true
        );
    }
};

然后在main.js引用该方法; Vue.directive('debounce', debounce);

使用

<el-button v-debounce>防抖提交</el-button>