news 2026/4/18 11:17:50

Vue.js 学习总结(19)—— Vue3 按钮防重复点击三种方案总结

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue.js 学习总结(19)—— Vue3 按钮防重复点击三种方案总结

前言

我们在使用 uniapp 开发完移动端项目之后,需要对程序的性能进行优化:比如防止按钮或者 view 重复点击等。下面是我给出的3种解决方案:

方案一:状态锁

核心:通过设置变量 true/false 来控制按钮或者 view 的状态。

这种方式应该最常见。

<template> <view> <!-- 作者:知否技术 --> <!--1. 视图 --> <view :class="{ 'disabled': isLoading }" @click="handleSubmit"> 提交 </view> <!--2. 按钮 disabled --> <uv-button :disabled="isLoading" @click="handleSubmit"> 提交 </uv-button> <!--3. 按钮 loading --> <uv-button :loading="isLoading" @click="handleSubmit">提交</uv-button> </view> </template> <script setup> import {ref} from 'vue' import orderApi from '@/api/order/order.js'; const isLoading = ref(false) // 提交方法 const handleSubmit = async () => { // 防止重复点击 if (isLoading.value) return // 锁住 isLoading.value = true try { const res = await orderApi.handleSubmit(order); if (res.code === 200) { getReturnFundList(); uni.showToast({ title: '提交成功' }); } else { uni.showToast({ title: '提交失败' }); } } catch (error) { console.error("提交失败:", error); } finally { // 解锁 isLoading.value = false; } } </script>

方案二:全局自定义防重复点击指令

在项目根目录中新建 /directives/preventClick.js :

1. preventClick.js

// 防止重复点击指令 exportconst preventClick = { // 指令绑定到元素时执行 mounted(el, binding) { // 1. 设置防抖间隔时间,默认1000毫秒 const delay = binding.value || 1000; // 2. 创建一个标记,记录当前是否可点击 el.isDisabledClick = false; // 3. 保存原始的点击事件处理函数 const originalClickHandler = el.__originalClickHandler; // 4. 创建新的点击事件处理函数 el.__preventClickHandler = (event) => { // 如果当前不可点击,直接拦截点击事件 if (el.isDisabledClick) { event.preventDefault(); // 阻止默认行为 event.stopPropagation(); // 阻止事件冒泡 return; } // 设置为不可点击状态 el.isDisabledClick = true; // 5. 执行原始的点击事件处理函数 if (originalClickHandler) { originalClickHandler(event); } // 6. 设置定时器,在指定时间后恢复点击 el.preventClickTimer = setTimeout(() => { // 恢复点击状态 el.isDisabledClick = false; // 清除定时器引用 el.preventClickTimer = null; }, delay); }; // 7. 移除原始的点击事件,添加新的点击事件 el.removeEventListener('click', originalClickHandler); el.addEventListener('click', el.__preventClickHandler); }, // 指令从元素解绑时执行 unmounted(el) { // 8. 清除定时器 if (el.preventClickTimer) { clearTimeout(el.preventClickTimer); el.preventClickTimer = null; } // 9. 移除事件监听器 if (el.__preventClickHandler) { el.removeEventListener('click', el.__preventClickHandler); el.__preventClickHandler = null; } // 10. 清除自定义属性 el.isDisabledClick = null; el.__originalClickHandler = null; } };

2. 在 main.js 中全局注册指令

import { createSSRApp } from'vue'; import App from'./App.vue'; // 导入指令 import { preventClick } from'@/directives/preventClick'; exportfunction createApp() { const app = createSSRApp(App); // 全局注册指令,指令名为 prevent-click app.directive('prevent-click', preventClick); return { app }; }

3.在组件中使用指令

<template> <view> <!-- 方式1:使用默认 1000ms 防抖 --> <button v-prevent-click @click="handleClick">点击</button> <!-- 方式2:自定义防抖时间 --> <button v-prevent-click="2000" @click="handleClick">点击</button> </view> </template>

方案三:封装一个防重复点击的 Hook

在项目目录 hooks 新建文件: usePreventReclick.js

import { ref } from'vue' exportfunction usePreventReclick(delay = 1000) { const isDisabled = ref(false) // 执行受保护的操作 fn - 要执行的函数(建议返回 Promise) // 返回 fn 的结果或 undefined(如果被阻止) const execute = async (fn) => { if (isDisabled.value) { console.info('操作被阻止') returnundefined } // 设置为 true isDisabled.value = true try { const result = await fn() return result } catch (error) { // 抛出异常 throw error } finally { // 延迟后自动重置状态 setTimeout(() => { isDisabled.value = false }, delay) } } // 解除禁用 const reset = () => { isDisabled.value = false } return { isDisabled, execute, reset } }

在项目中使用:

<template> <view class="container"> <button :disabled="isLoading" :loading="isLoading" @click="handleSubmit" > {{ isLoading ? '正在提交中...' : '提交订单' }} </button> </view> </template> <script setup> import { ref } from 'vue' import { usePreventReclick } from '@/hooks/usePreventReclick' const isLoading = ref(false) // 创建防重实例:时间 1500 毫秒 const { isDisabled: isLoading, execute } = usePreventReclick(1500) const handleSubmit = () => { execute(async () => { // 模拟后端请求 await new Promise() uni.showToast({ title: '提交成功'}) }).catch(err => { console.error('提交失败:', err) uni.showToast({ title: '提交失败'}) }) } </script>
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 7:51:33

git cherry-pick精选提交:在PyTorch-CUDA-v2.7中合并关键修复

git cherry-pick精选提交&#xff1a;在PyTorch-CUDA-v2.7中合并关键修复 在深度学习项目的日常开发中&#xff0c;一个看似微小的内存泄漏问题&#xff0c;可能让整个训练任务在数小时后崩溃。更糟糕的是&#xff0c;修复这个漏洞的代码可能藏在一个仍在开发中的功能分支里—…

作者头像 李华
网站建设 2026/4/18 9:45:34

49页可编辑精品PPT| 离散型制造行业智能工厂标准解决方案

离散型制造企业在日常运营中常面临多重挑战&#xff0c;如管理过程依赖人工导致制度难以落实&#xff0c;信息传递散落各环节造成集中管理缺失&#xff0c;订单成本难以准确核算&#xff0c;异常问题无法及时暴露&#xff0c;以及外协过程缺乏有效管理和延期无法快速识别等问题…

作者头像 李华
网站建设 2026/4/18 3:32:14

模型及MATLAB代码:考充分考虑并结合疫情下封控区域生活物资配送问题及车辆路径问题的特点构建...

模型及MATLAB代码&#xff1a;考充分考虑并结合疫情下封控区域生活物资配送问题及车辆路径问题的特点构建物资配送优化模型。 在一般单一目标——时间最短的基础上&#xff0c;加入综合满意率优化目标的路径优化问题 关键词&#xff1a;遗传算法、改进、模拟退火算法&#xff0…

作者头像 李华
网站建设 2026/4/18 10:05:12

解决PyTorch安装cuDNN不匹配问题:使用官方认证v2.7镜像

解决 PyTorch 安装 cuDNN 不匹配问题&#xff1a;使用官方认证 v2.7 镜像 在深度学习项目的开发过程中&#xff0c;最让人头疼的往往不是模型设计本身&#xff0c;而是环境配置——尤其是当 import torch 的一瞬间抛出一串 CUDA 或 cuDNN 相关错误时。你明明安装了最新版 PyTo…

作者头像 李华
网站建设 2026/4/13 15:54:39

web网页如何禁止别人移除水印

在网页中禁止用户移除水印是一个复杂的挑战&#xff0c;因为前端代码和页面内容本质上是由用户控制的。无法做到绝对禁止&#xff0c;但可以通过以下技术手段增加移除难度&#xff0c;并结合法律手段保护权益&#xff1a; 一、前端技术防护&#xff08;增加移除成本&#xff09…

作者头像 李华
网站建设 2026/4/18 5:37:59

零基础如何快速上手制作gif?GIF在线制作全攻略

在日常沟通、社交媒体分享或是工作汇报中&#xff0c;生动有趣的GIF图总能比静态图片更吸睛&#xff0c;轻松传递情绪与信息。相比于专业软件的复杂操作&#xff0c;在线制作GIF无需下载安装&#xff0c;打开gif在线制作工具就能上手&#xff0c;大大降低了制作门槛。下面就为大…

作者头像 李华