当前位置: 首页 > news >正文

vue防止按钮重复点击方案

vue防止按钮重复点击方案

按钮添加防止重复点击的原因有以下几个:
  • 用户操作习惯: 有些用户习惯性地快速点击多次,尤其是在感觉应用响应慢的时候。
  • 网络延迟: 点击按钮后,请求发送到服务器并返回响应需要时间。在此期间,如果按钮没有及时给出反馈或禁用,用户可能会认为第一次点击无效而再次点击。
  • 程序 Bug: 有时程序逻辑错误可能导致按钮状态未正确更新。
防止重复点击的方法有以下几种:
1.禁用按钮与状态锁定

在按钮点击时,将按钮设置为禁用状态,防止用户再次点击。当请求完成后,再将按钮恢复为可用状态。

<template><buttonid="submitBtn":class="{ 'is-loading-css': isLoading }"@click="handleSubmitWithCSS":disabled="isLoading">{{ buttonText }}</button>
</template><script setup lang="ts">
const buttonText = ref("提交");
const isLoading = ref(false);
const handleSubmitWithCSS = async () => {if (isLoading.value) return;isLoading.value = true;buttonText.value = "正在提交...";try {// 模拟异步操作await new Promise((resolve) => setTimeout(resolve, 2000));} catch (err) {console.log(err);} finally {isLoading.value = false;buttonText.value = "提交";}
};
</script><style scoped>
#submitBtn {padding: 10px 20px;background-color: #007bff;color: white;
}
/* 添加加载状态样式 */
.is-loading-css {position: relative;cursor: not-allowed;opacity: 0.7;
}/* 可选的加载动画 */
/* 可结合element el-loading 使用 */
.is-loading-css::after {content: "";position: absolute;right: 10px;top: 50%;width: 16px;height: 16px;margin-top: -8px;border: 2px solid rgba(255, 255, 255, 0.3);border-radius: 50%;border-top-color: white;animation: spin 0.8s linear infinite;
}@keyframes spin {to {transform: rotate(360deg);}
}
</style>
2.CSS pointer-events: none

点击后,给按钮添加一个 CSS 类,设置 pointer-events: none;,使其不再响应鼠标事件

...代码同上//css部分
.is-loading-css {pointer-events: none;
}
3.自定义指令
  • 新建 directives/throttleClick.js
//directives/throttleClick.js
import type { DirectiveBinding } from "vue";
// /获取统一配置对象
function getConfig(value) {if (typeof value === "function") {return {handler: value,loadingText: "处理中...",errorHandler: undefined,};}return {handler: value.handler,loadingText: value.loadingText,errorHandler: value.errorHandler,};
}
export default {mounted(el: Element, binding: DirectiveBinding) {console.log(el, binding);const { value, arg } = binding;const delay = arg ? parseInt(arg) : 1500; // 默认防重时间 1.5sconst config = getConfig(value); // 获取配置对象// 添加自定义禁用类名const disabledClass = "is-loading-css";el.addEventListener("click", async () => {// 检查是否已禁用if (el.classList.contains(disabledClass)) return;// 添加禁用状态el.classList.add(disabledClass);const originalText = el.textContent;if (binding.value?.loadingText) {el.textContent = binding.value.loadingText;}el.textContent = config.loadingText;try {// 执行绑定的函数const result = config.handler();// 如果返回的是 Promise,等待其完成if (result instanceof Promise) {await result;}} catch (error) {console.error("指令捕获的错误:", error);} finally {// 延迟后恢复按钮setTimeout(() => {el.classList.remove(disabledClass);el.textContent = originalText;}, delay);}});},
};
  • 注册指令
//main.js
import { createApp } from "vue";
import App from "./App.vue";import throttleClick from "./directives/throttleClick"; // 导入自定义指令const app = createApp(App);app.directive("throttleClick", throttleClick);
app.mount("#app");
  • 使用指令
<template><!-- 自定义指令用法1 --><!-- <buttonid="submitBtn"v-throttle-click:1000="{handler: handleSubmitWithCSS,loadingText: '提交中...',errorHandler: handleError}">{{ buttonText }}</button> --><!-- 自定义指令用法2 --><button v-throttle-click="handleSubmitWithCSS" id="submitBtn">{{ buttonText }}</button>
</template><script setup lang="ts">
const buttonText = ref("提交");const handleSubmitWithCSS = async () => {await new Promise((resolve) => setTimeout(resolve, 2000));console.log("表单提交成功!");
};
// const handleError = (err) => {
//   console.log(err); // 处理错误逻辑
// }
</script><style scoped>
#submitBtn {padding: 10px 20px;background-color: #007bff;color: white;
}
/* 添加加载状态样式 */
.is-loading-css {position: relative;cursor: not-allowed;opacity: 0.7;/* 点击后,给按钮添加一个CSS类,设置 pointer-events: none;,使其不再响应鼠标事件。 *//* pointer-events: none  */
}/* 可选的加载动画 */
.is-loading-css::after {content: "";position: absolute;right: 10px;top: 50%;width: 16px;height: 16px;margin-top: -8px;border: 2px solid rgba(255, 255, 255, 0.3);border-radius: 50%;border-top-color: white;animation: spin 0.8s linear infinite;
}@keyframes spin {to {transform: rotate(360deg);}
}
</style>
4.防抖函数(Debounce)
  • 防抖函数是一种延迟执行的函数,只有在一定时间内没有再次触发函数时才会执行。
<template><button @click="handleSubmit" id="submitBtn">提交</button>
</template><script setup lang='ts'>import { debounce } from 'lodash'; // 引入 lodash 的防抖函数const handleSubmitWithCSS = async() => {await new Promise(resolve => setTimeout(resolve, 2000));console.log('表单提交成功!');
}
const handleSubmit =debounce(async function() {handleSubmitWithCSS();}, 2000, { leading: false, trailing: true }); // 防抖函数,延迟2秒执行</script>

相关文章:

  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | FAQ Collapse(问题解答折叠面板)
  • 如何使用vue2设计提示框组件
  • python-docx 库教程
  • Linux内核学习资料-deepseek
  • OPenCV CUDA模块图形变换----构建透视变换映射表函数buildWarpPerspectiveMaps()
  • 【技术支持】Android11 中获取应用列表
  • AVCap视频处理成帧和音频脚本
  • React前端框架学习
  • Babylon.js引擎(二)
  • 【python】基于pycharm的海康相机SDK二次开发
  • 美团NoCode设计网站的尝试经验分享
  • 打卡第42天:简单CNN
  • 游戏日志统计操作次数前三的用户
  • Linux日志分割压缩实战指南
  • 手写RPC框架<四> 负载均衡
  • 不同厂商保障UEFI/BIOS安全的技术与机制详解
  • 界面控件DevExpress WPF v24.2新版亮点:报表等组件功能升级
  • thinkphp 一个系统在同一个域名下,一个文件夹下如何区分多站点——穷人的精致规划——仙盟创梦IDE
  • MyBatis实战指南(六)自动映射
  • 债券与股票:投资市场的两大基石
  • 程序员和做网站那个好找工作/沈阳百度seo关键词排名优化软件
  • 如何自己做网站挣钱/社群推广平台
  • 龙华营销型网站设计/惠州seo招聘
  • 近境制作官网/新乡百度网站优化排名
  • 今日的新闻头条10条/seo首页优化
  • 小程序商城装修/搜索引擎优化seo多少钱