防止按钮重复点击

三种方案防止用户重复点击按钮发起多次请求

问题

如何防止用户重复点击按钮导致多次请求?常见场景包括:用户手速快双击按钮、请求响应慢用户以为没生效再次点击、刷新页面后再次点击。

解答

方案一:防抖控制

在指定时间内,第一次点击后的其他点击无效,适合防止无意识的快速重复点击。

export default {
  data() {
    return {
      notAllowed: false,
      control: 300 // 默认300毫秒
    }
  },
  methods: {
    handleClick(event) {
      if (this.disabled || this.notAllowed) return;
      
      this.notAllowed = true;
      setTimeout(() => {
        this.notAllowed = false;
      }, this.control);
      
      this.$emit('click', event, this);
    }
  }
}

方案二:请求期间禁用按钮

点击后立即禁用按钮,等请求响应后再恢复,适合处理响应较慢的请求。

// 调用时传入 button 实例
doQuery(button) {
  this.FesApi.fetch('generalcard/query', {
    sub_card_type: this.query.sub_card_type,
    page_info: {
      pageSize: 10,
      currentPage: 1
    }
  }, {
    button: button // 传入按钮实例
  }).then(rst => {
    // 处理响应
  });
}

在 fetch 内部控制按钮状态:

const action = function (url, data, option) {
  // 请求前禁用按钮
  if (option.button) {
    option.button.currentDisabled = true;
  }
  
  const log = requsetLog.creatLog(url, data);
  
  return param(url, data, option)
    .then(success, fail)
    .then((response) => {
      requsetLog.changeLogStatus(log, 'success');
      if (option && option.button) {
        option.button.currentDisabled = false;
      }
      return response;
    })
    .catch((error) => {
      requsetLog.changeLogStatus(log, 'fail');
      if (option && option.button) {
        option.button.currentDisabled = false;
      }
      error.message && window.Toast.error(error.message);
      throw error;
    });
}

方案三:重要接口时间间隔控制

针对关键操作,设置最小请求间隔,间隔过短时弹窗二次确认。

// 配置重要接口
this.FesApi.setImportant({
  'generalcard/action': {
    control: 10000, // 10秒内不允许重复请求
    message: '您在十秒内重复发起手工清算操作,是否继续?'
  }
});

在 fetch 中检查请求间隔:

api.fetch = function (url, data, option) {
  if (requsetLog.importantApi[url]) {
    const logs = requsetLog.getLogByURL(url, data);
    // 检查时间间隔,过短则弹窗确认
  }
  // 继续执行请求
}

关键点

  • 防抖方案适合防止无意识的快速重复点击,默认 300 毫秒间隔
  • 请求期间禁用按钮可以防止用户因响应慢而重复点击
  • 重要接口应设置最小时间间隔并二次确认,防止页面刷新后的重复操作
  • 前端防护只是第一层,后端接口必须设计成幂等性以应对恶意请求