前端vue中防止用户短时间内多次点击按钮触发点击事件解决方法
1.按钮点击后添加loading,接口返回成功后再移除loading(经过多次尝试发现,此方法不能完全确保只调用一次接口,第二次添加时仍会多次调用接口),方法如下:
html代码:
<el-button @click="onSave" :loading="onLoading">保存</el-button>
javascript代码:
<script> export default { data() { return { onLoading: false, }; }, methods: { onSave() { this.onLoading = true; let parmas = { //这里是接口传入参数 }; insert(parmas) .then((res) => { if (res.code === 200) {this.$message.success(res.message); this.onLoading = false; } else { this.$message.error(res.message); this.onLoading = false; } }) .catch((error) => { console.log(error); }); }, }, }; </script>
2.在规定时间内禁用按钮,按钮无法点击,即实现接口不被多次调用,方法如下:
html代码:
<el-button @click="onSave" :disabled="isdisabled">保存</el-button>
javascript代码:
<script> export default { data() { return { isdisabled: false, }; }, methods: { onSave() { this.isdisabled = true; //这里使用定时器解除按钮禁用 setTimeout(() => { this.isdisabled = false; }, 1500); let parmas = { //这里是接口传入参数 }; insert(parmas) .then((res) => { if (res.code === 200) {this.$message.success(res.message); } else { this.$message.error(res.message); } }) .catch((error) => { console.log(error); }); }, }, }; </script>
3.使用Vue自定义全局指令或局部指令
html代码:
<el-button @click="onSave" v-preventReClick>保存</el-button>
- 自定义全局指令
javascript代码:
//使用Vue.directive()来自定义全局注册指令,在main.js中加入下方这段代码,可以全局应用 Vue.directive("preventReClick", { inserted(el, binding) { el.addEventListener("click", () => { if (!el.disabled) { el.disabled = true; setTimeout(() => { el.disabled = false; }, binding.value || 2000); } }); }, });
- 自定义局部指令
javascript代码:
//在export default {} 中加入下方这段代码,可以局部应用 directives: { preventReClick: { // 指令的定义 inserted(el, binding) { el.addEventListener('click', () => { if (!el.disabled) { el.disabled = true setTimeout(() => { el.disabled = false }, binding.value || 2000) } }) } } }
4.使用节流函数
节流:是指一种在指定事件防止函数被频繁调用的思想
节流函数:是结合时间戳封装的函数,在指定时间内会调用一次方法
html代码:
<el-button @click="getTrottle">保存</el-button>
javascript代码:
<script> const throttle = (func, wait = 50) => { //上一次执行该函数的时间 let lastTime = 0; return function (...args) { // 当前时间 let now = +new Date(); // 将当前时间和上一次执行函数时间对比 // 如果差值大于设置的等待时间就执行函数 if (now - lastTime > wait) { lastTime = now; func.apply(this, args); } }; }; export default { data() { return { getTrottle: undefined, }; }, created() { this.getTrottle = throttle(this.onSave, 3000); }, methods: { onSave() { let parmas = { //这里是接口传入参数 }; insert(parmas) .then((res) => { if (res.code === 200) { this.$message.success(res.message); } else { this.$message.error(res.message); } }) .catch((error) => { console.log(error); }); }, }, }; </script>
以上就可以实现了,如果需要多次使用节流函数,也可以封装后再使用:
// 封装节流函数 // 参数:1.回调函数,2.时间,3.布尔值 // 时间戳: 毫秒值 // 相差的毫秒值 = 结束的时间戳 - 开始的时间戳 function trottle(callback,times,bool) { // 记录开始的时间戳 var startTime = new Date().getTime(); // 记录布尔值 var fistFlag = bool; // 返回function函数 (事件函数) return function() { // 记录结束的时间戳 var endTime = new Date().getTime(); // 相差的毫秒值 var totalTime = endTime - startTime; // 记录事件对象 var args = arguments[0]; // 判断布尔值是否为true if(fistFlag){ if(typeof callback == "function"){ // 调用回调函数 callback(args); // 设置布尔值为false fistFlag = false; // 重置开始的时间戳 startTime = endTime; } } // 判断是否达到指定的时间 if(totalTime >= times){ // 符合条件执行回调函数 if(typeof callback == "function"){ // 调用回调函数 callback(args); // 重置开始的时间戳 startTime = endTime; } } } }
5.使用Vue事件修饰符
<el-button v-on:click.once="onSave" :loading="onLoading">保存</el-button>