对于一些涉及后端接口请求的单击事件,不论后端是否作了请求限制,前端仍是有必要进行点击防重处理的。前端
这样既能减小对服务器端的压力,也能有效防止因重复请求而形成一些不可预期的异常。小程序
尤为是接口请求结果处理的逻辑中有须要调用小程序api,如获取手机号码受权、支付、领取卡券这些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) index=0; if (!isClick[index]) { isClick[index] = true setTimeout(function() { isClick[index] = false }, 500); return false; } else { return true; } } module.exports = { preventDuplicateClicks: preventDuplicateClicks }
调用方法:
//不处理冲突 if (utils.preventDuplicateClicks()) return; //处理冲突 if (utils.preventDuplicateClicks(1)) return;
这样的话,只要不一样的单击事件传的参数不一样,那么不一样单击事件的点击防重就不会冲突。
注意:
1.点击防重对单击事件锁定的时间通常半分钟足够了,若是涉及到小程序API调用,如支付、领取卡券类的API,调起API相应页面的时间通常都会有点久(大于500ms),能够把这个值设置成1000ms,对用户体验不会有影响的,毕竟微信支付、领取卡券之类的界面加载出来没那么快,用户基本上感受不到咱们点击防重的。
2.若是有须要,给 preventDuplicateClicks 方法再增长一个锁定时间的参数,这样使用起来更灵活,能够知足不一样需求。