对于防止按钮重复点击的尝试详解


Posted in Javascript onApril 22, 2019

导语:随着接触的项目增加,很多项目都是遇到同样的问题,而每次都是使用一贯的手法进行处理。有时候有些方法并不是那么的优雅甚至有些冗余,所以自己也想开始尝试不同的方法去解决同样的问题。

我经常在项目中会遇到按钮重复点击后引起表单的重复点击问题。所以针对这个问题,自己尝试了几种办法分别去解决。直接上代码。

1.粗暴简单办法

直接定义一个变量,每次点击过后等所有操作结束后释放变量。或使用loading防止用户点击

//* 部分代码
<script>
export default {
  methods: {
    onSubmit() {
      if (this.lock) return;
      this.lock = true;
      // const load = this.$loading();
      this.$http.create().then((res) => {
        // do something
        this.lock = false;
        // load.close();
      }).catch(() => {
        this.lock = false;
        // load.close();
      })
    }, 
  },
}
</script>

这种办法简单粗暴,但是每次需要防止重复点击的地方,都要去关注lock或者loading的重置,总觉的很??隆R裁话旆ê煤玫某槔氤隼础#?S:能力有限,自己也没有想到比较好的办法在上层优雅的封装出来)

2.直接把loading放到http请求中去做,统一封装方法

//* 部分代码
...
let load;
http.interceptors.request.use((config) => {
  load = Loading();
  ...
  return config;
}, error => {
  load.close();
  return Promise.reject(error)
});

http.interceptors.response.use((response) => {
  load.close();
  ...
  return response; 
},error => {
  load.close();
  return Promise.reject(error);
});

这种办法在实际中也用过了一段时间,一开始挺好用的,但是在后面自己弱网测试的时候发现也是会导致重复点击的情况。而且在有些时候loading图并不是所有请求都需要,还要去做个是否显示loading的配置,这样感觉http请求又笨重了,也没有让重复点击功能抽离出来。

3.装饰器方法

说到装饰器,最经典的应用场景就是面向切片编程(AOP),《前端常用设计模式(1)--装饰器(decorator)》juejin.im/post/5cb415… 做出了很棒的理解与应用。得益于ES7和TS,装饰器在Angular和react中都有很多案例,因为Vue中Class不是必选,所以在Vue中很少看到使用装饰器的,得益于官方有vue-class-component来使用Class进行创建组件的方法,开始了自己的尝试之路。

lock.js

export function lock(target, key, desc) {
  const fn = desc.value;
  //* 没有使用箭头函数是为了让this能指回到vue,这样就可以获取到vue的data,从而做更多的事情,下面会讲到
  desc.value = async function() {
    if (this.$lock) return;
    this.$lock = true;
    await fn.apply(this).catch(() => {
      this.$lock = false;
    });
    this.$lock = false;
    return target;
  };
}

index.vue

<template>
  <!-- do something -->
</template>
<script>
import Vue from 'vue';
import Component from 'vue-class-component';
import { lock } from './lock';

@Component
export default class extends Vue {
  @lock
  async onSubmit() {
    await this.$http.create();
    // do something
  }
}
</script>

感觉这样就完全抽离了重复点击的功能(PS:好像是这样的),也能独立测试,想在哪里用就在哪里用。感觉不足的是,装饰器里需要让this重新指回vue才能获取到vue的data

4.举一反三

既然重复点击可以从业务代码中抽离出来,那我们提交表单的字段验证也就同样可以抽离出来了。(PS:所有UI框架都有成熟的form表单验证组件,就当我是瞎折腾)

validate.js

export function validate(target, key, desc) {
 const fn = desc.value;

 desc.value = async function () {
  const {
   name, phone,
  } = this.data;
  
  if (!name) {
   return confirm('请输入您的姓名');
  }
  if (name.length > 20) {
   return confirm('您的姓名不能超过20个字');
  }
  if (!phone) {
   return confirm('请输入您的电话');
  }
  if (!((/^\d{11}$/.test(phone)))) {
   return confirm('请输入11位的电话号码');
  }
  
  await fn.apply(this);
  return target;
 };
}

index.vue

<template>
  <!-- do something -->
</template>
<script>
import Vue from 'vue';
import Component from 'vue-class-component';
import { validate } from './validate';

@Component
export default class extends Vue {
  data = {
    name: '',
    phone: '',
  }
  
  @validate
  async onSubmit() {
    await this.$http.create();
    // do something
  }
}
</script>

5.防抖方法(补充)

有小伙伴说可以使用防抖,个人觉得还是需要看场景,这里也就列出防抖的方法。

防抖方法是一个很好限制重复事件频繁触发的,经常用在scroll、resize事件上,也可以尝试用在重复点击上面。但是如果点击事件后需要有异步处理,单单使用防抖方法也会没办法限制弱网(PS:吐槽一下成都地铁上移动经常网络不好)下重复点击的情况。如:防抖时间为1秒,但是请求花掉了2秒才返回数据给前端进行处理,中间产生了时间差,导致用户有时间重复点击。所以个人觉得还是需要配合其它办法。同样列出防抖的列子:

throttle.js

const throttle = function(fn, wait, scope) {
  clearTimeout(throttle.timer);
  throttle.timer = setTimeout(function() {
    fn.apply(scope);
  }, wait);
};

index.vue

<template>
  <!-- do something -->  
</template>
<script>
export default {
  onSubmit() {
    throttle(() => {
      this.$http.create().then((result) => {
        // do something
      });
    }, 1000);
  },
};
</script>

以上所述是小编给大家介绍的对于防止按钮重复点击的尝试详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
基于jQuery的Spin Button自定义文本框数值自增或自减
Jul 17 Javascript
20款非常优秀的 jQuery 工具提示插件 推荐
Jul 15 Javascript
Javascript设计模式之观察者模式的多个实现版本实例
Mar 03 Javascript
PHP结合jQuery实现的评论顶、踩功能
Jul 22 Javascript
基于zepto的移动端轻量级日期插件--date_picker
Mar 04 Javascript
jQuery图片切换动画特效
Nov 02 Javascript
JavaScript函数节流的两种写法
Apr 07 Javascript
详解JavaScript中的数组合并方法和对象合并方法
May 11 Javascript
javascript中toFixed()四舍五入使用方法详解
Sep 28 Javascript
详解vue.js移动端配置flexible.js及注意事项
Apr 10 Javascript
layui监听下拉选框选中值变化的方法(包含监听普通下拉选框)
Sep 24 Javascript
抖音短视频(douyin)去水印工具的实现代码
Mar 30 Javascript
Vue render函数实战之实现tabs选项卡组件
Apr 22 #Javascript
详解Vue依赖收集引发的问题
Apr 22 #Javascript
JS大坑之19位数的Number型精度丢失问题详解
Apr 22 #Javascript
Vue $mount实战之实现消息弹窗组件
Apr 22 #Javascript
深入理解vue中的slot与slot-scope
Apr 22 #Javascript
浅析vue插槽和作用域插槽的理解
Apr 22 #Javascript
详解50行代码,Node爬虫练手项目
Apr 22 #Javascript
You might like
php设计模式 Template (模板模式)
2011/06/26 PHP
php输入流php://input使用示例(php发送图片流到服务器)
2013/12/25 PHP
Laravel网站打开速度优化的方法汇总
2017/07/16 PHP
PHP使用SOAP调用API操作示例
2018/12/25 PHP
Laravel 对某一列进行筛选然后求和sum()的例子
2019/10/10 PHP
jquery批量控制form禁用的代码
2013/08/06 Javascript
JS获得浏览器版本和操作系统版本的例子
2014/05/13 Javascript
Javascript验证用户输入URL地址是否为空及格式是否正确
2014/10/09 Javascript
JS实现可拖曳、可关闭的弹窗效果
2015/09/26 Javascript
安装使用Mongoose配合Node.js操作MongoDB的基础教程
2016/03/01 Javascript
bootstrap3-dialog-master模态框使用详解
2017/08/22 Javascript
js插件实现图片滑动验证码
2020/09/29 Javascript
利用ES6实现单例模式及其应用详解
2017/12/09 Javascript
详解基于Vue-cli搭建的项目如何和后台交互
2018/06/29 Javascript
JS/HTML5游戏常用算法之路径搜索算法 随机迷宫算法详解【普里姆算法】
2018/12/13 Javascript
百度小程序自定义通用toast组件
2019/07/17 Javascript
vue实现从外部修改组件内部的变量的值
2020/07/30 Javascript
npm ci命令的基本使用方法
2020/09/20 Javascript
使用python搭建Django应用程序步骤及版本冲突问题解决
2013/11/19 Python
利用Python进行异常值分析实例代码
2017/12/07 Python
Sanic框架请求与响应实例分析
2018/07/16 Python
python协程gevent案例 爬取斗鱼图片过程解析
2019/08/27 Python
解决Python图形界面中设置尺寸的问题
2020/03/05 Python
Jupyter Notebook打开任意文件夹操作
2020/04/14 Python
Pycharm激活方法及详细教程(详细且实用)
2020/05/12 Python
零基础学Python之前需要学c语言吗
2020/07/21 Python
Django admin组件的使用
2020/10/24 Python
基于Python的接口自动化读写excel文件的方法
2021/01/15 Python
JD Sports瑞典:英国领先的运动时尚商店
2018/01/28 全球购物
东方红海科技面试题软件测试方面
2012/02/08 面试题
周年庆促销方案
2014/03/15 职场文书
2014旅游局党组书记党建工作汇报材料
2014/11/02 职场文书
大三学生英语考试作弊检讨书
2015/01/01 职场文书
单位推荐信范文
2015/03/27 职场文书
新闻报道稿范文
2015/07/23 职场文书
2015年小学体育教师工作总结
2015/10/23 职场文书