Bootstrap

Vue-防止重复点击指令

背景

在日常业务开发中,经常会需要处理按钮防止重复点击事件,因为在提交订单支付金额的场景需要只触发一次,多次触发会导致业务异常

Vue局限

vue的事件响应是通过事件队列实现的,在极限情况(快速点击)是没办法防止按钮多次触发,即使使用了$nextTick,也只是延迟触发,没办法保证按钮不会重复触发

解决方案

我通过闭包创建一个状态机,实时管理状态变化,减少中间环节,从而实现数据快速响应

// 状态机,用于简单判断状态,用于防止按钮极限快速点击
je.status = (function () {

  let loading = false;

  function lock() {

    loading = true;
  }

  function unlock() {

    loading = false
  }

  function getStatus() {

    return loading;
  }

  return {
    lock,
    unlock,
    getStatus
  }
})()

通过立即执行函数,把一部分状态存储在内存

指令

Vue.directive('singleClick', function (el, binding) {

  el.onclick = function (event) {

    if (el.disabled) return;

    if (je.status.getStatus() === true) {

      return;
    }
    je.status.lock();
    binding.value();
  }
})

如何使用

提交发布

commitData() {
      this.$refs.telexForm.verify((val) => {
        if (val) {
          this.$api.post('/post/v1/post', this.form).then((res) => {
            this.$Message.success('提交成功!')
            this.$router.push({
              path: '/content/list',
            })
            je.status.unlock()
          })
        } else {
          this.$Message.error('必填项不能为空!')
          je.status.unlock()
        }
      })
    }

重点

由于一般提交数据都是异步,前端没办法预估事件什么时候结束,所以需要在接口请求完数据,再改变状态

优点

通过指令的方式,和@click一致,把复杂逻辑封装在指令中,可以减少学习成本,无缝切换。