防止按钮重复点击
三种方案防止用户重复点击按钮发起多次请求
问题
如何防止用户重复点击按钮导致多次请求?常见场景包括:用户手速快双击按钮、请求响应慢用户以为没生效再次点击、刷新页面后再次点击。
解答
方案一:防抖控制
在指定时间内,第一次点击后的其他点击无效,适合防止无意识的快速重复点击。
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 毫秒间隔
- 请求期间禁用按钮可以防止用户因响应慢而重复点击
- 重要接口应设置最小时间间隔并二次确认,防止页面刷新后的重复操作
- 前端防护只是第一层,后端接口必须设计成幂等性以应对恶意请求
目录