对于一些涉及后端接口请求的单击事件,不论后端是否做了请求限制,前端还是有必要进行点击防重处理的。

这样既能减少对服务器端的压力,也能有效防止因重复请求而造成一些不可预期的异常。

尤其是接口请求结果处理的逻辑中有需要调用小程序api,如获取手机号码授权、支付、领取卡券这些API。

虽然这些API都能调起自己的原生界面,但是从请求到相关原生界面展示出来之前是会有一定的时间的,如果在这个空档用户快速点击,那么就会造成接口被重复请求,直接回影响到小程序API的调用。

对于点击防重,以前用过一种比较笨的方法,就是自定义loading组件,在接口请求开始前loading,API调用complete回调中隐藏loading。

自定义loading组件点击防重:

之所以自定义loading,是由于小程序的showToast和showLoading只能显示一个,为了避免showToast的影响,我们需要自定义一个loading组件;

loading组件需要有蒙板,这样loading的时候能隔离页面,有效的屏蔽点击(蒙板可以设置一个蒙板是否透明的参数,正常调用显示半透明灰底蒙板,涉及到小程序API不需要灰底蒙板的就显示透明蒙板)。

当然,这种做法只不过是避免showToast影响showLoading的同时,还可以做点击防重,如果仅仅是点击防重,这代码量就比较多了。

如果原生的loading就能满足需求,那么可以采用下面的方法进行点击防重:

定义点击标志变量进行点击防重:

Page({
data: {
......
isclick: false, //点击防重标志
},
/**
* 需要做防点击防重的单击事件
*/
onclick: function() {
var self = this
if(!self.data.isclick){
self.setData({
isclick:true
})
setTimeout(function () {
self.setData({
isclick: false
})
}, 500);
}else{
return;
}
......
}
......
})

这种方法,就简单多了。这里采用了定时器放开点击状态,非特殊情况,500ms后放开点击状态也足够用了,也不会对用户体验造成影响。

当然,如果你不想这么做,可以在指定接口调用成功之后或某些操作完成后再放开点击状态,但有风险的地方就在于如果这个过程中一个地方出问题,那么很可能这个单击事件已经被锁定而无法放开了,用户重试的机会都没有,所以这种方法慎用。

对于上边的代码,如果需要用到的地方比较多,可以封装到公共方法文件中:

//util.js

//点击防重
let isClick=false;
let preventDuplicateClicks=function(){
if (!isClick) {
isClick=true
setTimeout(function () {
isClick = false
}, 500);
return false;
} else {
return true;
}
}
module.exports = {
preventDuplicateClicks: preventDuplicateClicks
}

方法调用:

import utils from '../../utils/util.js'
Page({
......
/**
* 1.需要防重的单击事件
*/
orderPay: function() {
var self = this
if(utils.preventDuplicateClicks()) return;
......
},
......
})

上边代码并没有处理多个单击事件的冲突问题,毕竟是同一个标志变量。但是一般情况下,用户连续点击两个按钮的时间已经超过500ms了(有意测试除外)。如果一定要解决,那么可以用数组来区分不同的单击事件,示例代码如下:

/**
* 点击防重函数
* 需要避免冲突的单击事件需要传不同的index参数,如果不传视为不处理冲突,共用一个标志值
*/
let isClick = [];
let preventDuplicateClicks = function(index) {
if (!index || isNaN(index)) index = 0;
if (!isClick[index]) {
isClick[index] = true
console.log(isClick)
setTimeout(function() {
isClick[index] = false
}, 1000);
return false;
} else {
return true;
}
}
...
module.exports = {
preventDuplicateClicks
}

调用方法:

//不处理冲突
if (utils.preventDuplicateClicks()) return; //处理冲突
if (utils.preventDuplicateClicks(1)) return;

这样的话,只要不同的单击事件传的参数不同,那么不同单击事件的点击防重就不会冲突。

注意:

1.点击防重对单击事件锁定的时间一般半分钟足够了,如果涉及到小程序API调用,如支付、领取卡券类的API,调起API相应页面的时间一般都会有点久(大于500ms),可以把这个值设置成1000ms,对用户体验不会有影响的,毕竟微信支付、领取卡券之类的界面加载出来没那么快,用户基本上感觉不到我们点击防重的。

2.如果有需要,给 preventDuplicateClicks 方法再增加一个锁定时间的参数,这样使用起来更灵活,可以满足不同需求。

微信小程序开发——点击防重的解决方案的更多相关文章

  1. 微信小程序开发——点击按钮获取用户授权没反应或反应很慢的解决方法

    异常描述: 点击按钮获取用户手机号码,有的时候会出现点击无反应或很久之后才弹出用户授权获取手机号码的弹窗,这种情况下,也会出现点击穿透的问题(详见:微信小程序开发——连续快速点击按钮调用小程序api返 ...

  2. 微信小程序开发——点击按钮退出小程序的实现

    微信小程序官方是没有提供退出的API的,但是在navigator这个组件中,是有退出这个功能的:详情参考官方文档:navigator.示例代码:1 navigator open-type=" ...

  3. 微信小程序开发 -- 点击右上角实现转发功能

    // 在page的js文件中加入以下代码/** * 用户点击右上角分享 */ onShareAppMessage: function () { }

  4. 微信小程序开发 (资料汇总,谁还没被坑过?希望助你绕过一些坑)

    最近帮人家做一个微信小程序,刚好想熟悉一下.由于牵扯到多用户使用系统,以及数据共享,所以自然架构选择了,客户端和服务器的方式. 后台服务器是windows server,后台程序是.Net  WebA ...

  5. 微信小程序开发中的二三事之网易云信IMSDK DEMO

    本文由作者邹永胜授权网易云社区发布. 简介 为了更好的展示我们即时通讯SDK强悍的能力,网易云信IM SDK微信小程序DEMO的开发就提上了日程.用产品的话说就是: 云信 IM 小程序 SDK 的能力 ...

  6. 微信小程序开发资源整理

    有兴趣学习微信小程序开发的可以关注简书专题 微信小程序开发 由于微信已经开发文档和开发工具了,所以下面的内容用处不大了. 具体参考:http://mp.weixin.qq.com/wiki/ 这篇文章 ...

  7. 微信小程序开发心得

    微信小程序也已出来有一段时间了,最近写了几款微信小程序项目,今天来说说感受. 首先开发一款微信小程序,最主要的就是针对于公司来运营的,因为,在申请appid(微信小程序ID号)时候,需要填写相关的公司 ...

  8. 微信小程序开发日记——高仿知乎日报(下)

    本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP 要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该 ...

  9. 微信小程序开发日记——高仿知乎日报(中)

    本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该教 ...

随机推荐

  1. hibernate left join fetch 出错的问题

    1.首先说说manyToOne的问题 比如一个用户所在的组织机构,可能是多个,最多是四个,然后userEntity有下的代码: 关联查询: 第一种方式:代码如下 StringBuilder sql = ...

  2. jar包和war包的介绍和区别

    jar包和war包的介绍和区别 Java程序员的日常 关注 做Java开发,jar包和war包接触的挺多的,有必要对它们做一个深入的了解,特总结整理如下: 1.jar包的介绍 JAR(Java Arc ...

  3. 在linux上构建gitolite

    每台机器生成密钥前要设置邮箱和用户名: git config --global user.name "admin" git config --global user.email & ...

  4. realm清空所有数据库的数据

    /* *清空数据库 */ public int clearDatabase() { Realm realm = Realm.getDefaultInstance(); try { realm.begi ...

  5. LSTM编程所用函数

    1.Round函数返回一个数值,该数值是按照指定的小数位数进行四舍五入运算的结果.可是当保留位跟着的即使是5,有可能进位,也有可能舍去,机会各50% 2.python基础 (1)@property 特 ...

  6. DeprecationWarning

    当我在导入sklearn这个库的时候,程序抛出了一个丢弃警告,它的意思是在版本更新后imp库已经不用了,用importlib来代替这个库 Warning (from warnings module): ...

  7. 七层协议&网络配置

    1.输入CMD 2.ipconfig-all 可查看详细的电脑网络配置,子网掩码(subnet mask)又叫网络掩码.地址掩码.子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网 ...

  8. Android 开发 Camera类的拍照与录像

    前言 在开发Android应用的时候,如果需要调用摄像头拍照或者录像,除了通过Intent调用系统现有相机应用进行拍照录像之外,还可以通过直接调用Camera硬件去去获取摄像头进行拍照录像的操作.本篇 ...

  9. Delphi 字母 递增 递减算法

    网上看了一下,好象没有现成的,自己随手写了一下,给大家参考一下吧 // a..z 97..122 A..Z 65..90 function UpABC(ABC : String; AddCount : ...

  10. Ubuntu安装后上网问题,

    首先VMware网络配置详解一:三种网络模式简介 http://www.cnblogs.com/gylei/archive/2012/04/06/2435087.html 很详细. 此处讲述通过桥接来 ...