【自定义指令】debounce解决快速点击导致重复触发问题

85 阅读2分钟

在项目开发中,点击按钮提交表单是比较常见的需求,在某些情况下,用户可能会快速连续触发同一个事件,这可能导致不必要的重复操作或性能问题。为了解决这个问题,我们可以使用防抖技术(确保函数在一段时间内只执行一次)。像后台管理系统有多个页面用到,因此我们可以封装为指令。

技术栈:Vue(3.5.12)、TypeScript(5.1.6)、Element Plus(2.8.8)、UnoCSS(0.55.2)

  •  指令TypeScript脚本

  1. 指令名称:我们定义了一个名为 debounce 的自定义指令。
  2. 延迟时间:可以通过指令的参数来指定防抖动的延迟时间,默认是 300 毫秒。
  3. 创建防抖动函数:使用 lodash-es 提供的 debounce 函数来创建防抖动函数。
  4. 事件绑定:在元素上绑定防抖动函数,并在元素卸载时移除绑定。
import type { DirectiveBinding } from 'vue'
import { debounce } from 'lodash-es'

interface ElType extends HTMLElement {
  __debouncedFn__?: () => void
}

export default {
  name: 'debounce',
  option: {
    mounted: (el: ElType, binding: DirectiveBinding) => {
      if (typeof binding.value !== 'function') {
        console.warn('v-debounce: provided expression must be a function')
        return
      }

      // 如果传递了参数就用参数,否则默认300毫秒
      const delay = binding.arg ? parseInt(binding.arg, 10) : 300

      // 创建 debounced 函数
      const debouncedFn = debounce(binding?.value, delay)

      // 在元素上存储 debounced 函数,以便在卸载时可以访问它
      el.__debouncedFn__ = debouncedFn

      // 添加事件监听
      el.addEventListener('click', debouncedFn)
    },
    beforeUnmount(el: ElType) {
      // 移除事件监听
      if (el.__debouncedFn__) {
        el.removeEventListener('click', el.__debouncedFn__)
        delete el.__debouncedFn__
      }
    }
  }
}

  • 引入并注册指令

在main.ts中添加指令相关的代码:

import vDebounce from './directives/clickDebounce' // 假设指令文件位于 src/directives/clickDebounce.ts

const app = createApp(App);

// 注册全局指令
app.directive(vDebounce.name, vDebounce.option)

app.mount('#app');

  • 模板中使用

默认防抖动的延迟时间是300毫秒,如需修改请改成:v-debounce:1000(你期望的时间)

<template>
  <el-button v-debounce="handleClick" type="primary">确认</el-button>
</template>

<script setup>
function handleClick() {
  console.log('Button clicked!')
}
</script>

实现效果

​编辑

需求拓展

想到有时输入框或者其他业务也有做防抖的需求,或许可以拓展一下指令,兼容其他的事件,一劳永逸。还没想好怎么实现,先立个flag。

编辑

以上就是自定义防抖指令的实现啦^-^