前言:html
小程序開發中諸如獲取用戶手機號碼、調起微信支付、領取卡券等api都是會有必定的延遲的。也就是說經過點擊按鈕調用這些api的時候,從點擊按鈕調用api,到支付頁面或者領取卡券界面展現出來是須要必定時間的,連續點擊按鈕,仍是有可能會重複調用的。小程序
雖然這種狀況有點極端,正經常使用戶是不會這麼連續快速的點擊按鈕的,可是也不能排除有用戶手抖,連續點了兩下。若是重複調用的話,不只體驗很差,單擊事件中涉及到後端接口操做的也可能引發其餘異常。因此這個問題仍是要處理下的。後端
剛開始想到的是使用loading開啓模板來防止點擊穿透,結果發現loading從調用到蒙板起做用也是須要必定時間的,仍是解決不了這個問題(自定義loading加蒙板防點擊穿透應該能夠的)。後邊就想到了採用給按鈕添加啓用/禁用狀態來控制按鈕點擊的頻率——點擊按鈕,按鈕狀態設置爲禁用,必定時間以後,啓用按鈕可用狀態。經屢次驗證,此法可行。微信小程序
處理方法:api
1. 設置按鈕可用狀態:服務器
Page({ data: { disabled: false //購買按鈕是否可用,按鈕默承認用,點擊一次後置爲不可用,必定時間以後恢復可用 }, /** * 購買按鈕點擊防重:禁用/啓用 */ buyBtnDisable: function() { this.setData({ disabled: true }) var self = this setTimeout(function() { self.setData({ disabled: false }) }, 1000) } })
在每個調用小程序api的按鈕單擊事件中先調用這個函數,則必定時間以內,這個按鈕是禁用狀態,就不會再重現重複點及的問題了。微信
2. 自定義loading:xss
建立模板或組件loading,在頁面中直接使用該模板替代微信loading組件就行了,因爲:函數
loading.wxml微信支付
<template name="loading"> <view class='loading'> <view class='bg'> <image src='https://lg-gc2dnftu-1257370699.cos.ap-shanghai.myqcloud.com/timg.gif' width="100" height="100"></image> </view> </view> </template>
loading.wxss
.loading{ position: absolute; top:0; left:0; width:100%; height:100%; } .bg{ background: rgba(0,0,0,0.7); width:200rpx; height:200rpx; margin:50% auto; border-radius: 10rpx; padding-top:70rpx; box-sizing: border-box; } .loading image{ display: block; width:60rpx; height:60rpx; margin:0 auto; }
這樣就可使用自定義loading替代微信小程序原生loading了,經驗證,此方法能解決屢次點擊按鈕重複調用api的問題。
關於模板具體使用詳見:http://www.javashuo.com/article/p-unxlfhrg-eu.html
結語:
經驗證,上邊兩種方法都能有效解決按鈕連續點擊重複調用微信api的問題,且兩種方法都須要放在單擊事件的開頭在單擊事件中先行運行。
採用設置按鈕狀態的方法比較獨立,只須要在單擊事件開頭就調用函數就好,函數會在指定時間以後恢復按鈕的可點擊狀態,不會對後續代碼有太大影響(可是這種方法會暫時屏蔽按鈕的啓用狀態,指定時間內再次點擊是無效的)。
採用自定義loading方式是使用蒙版覆蓋了按鈕,本質上未對按鈕作任何修改,只是在loading展現的期間沒法點擊而已。缺點就是在後續的代碼中關閉loading,loading的關閉也是須要必定時間的。若是是調用獲取用戶手機號碼受權的api,取消受權的時候關閉loading,則會在取消以後,loading還會顯示一下再消失,體驗有點不太好。
綜上,上邊兩種方法各有優劣,能夠根據本身的須要選擇使用。
後續改進:
2018.9.27
1. 鑑於方法1會直接改變按鈕的可點擊狀態,設置禁用時間太短則無效,過長則會致使必定時間內按鈕點擊無反應,並且這個時間很差肯定,故選用自定義loading方法;
2. 對loading組件進行改進,新增了 transparent 來控制loading組件加載圖標及其半透明的模塊背景的顯隱:
之因此有這個改進,是針對單擊事件中同時有後端接口訪問和微信api調用的狀況。通常loading是針對服務器端接口訪問進行使用的——調用接口以前顯示loading,接口響應成功,loading關閉。但若是在調用服務器端接口成功以後須要同步調用微信小程序的api,以下單以後須要調起微信api進行支付,那麼在調起微信支付先後也是要使用loading作下蒙板來防止重複點擊按鈕。
在調用小程序api的過程當中直到支付界面展現出來,loading消失,這個過程當中,按鈕被loading的蒙板擋着,能夠有效的防止重複點擊。可是對於獲取手機號碼受權及微信支付都是以彈窗的形式展現的,因此在調用小程序api直到彈窗彈出的過程當中,loading是會一直展現的,這樣體驗就不太好了。解決這個問題,比較好的就是隱藏掉loading的菊花圖標及半透明層,也就是僅充當一個透明蒙板來使用,這樣即能防止按鈕重複點擊,也不影響展現。
組件模板代碼:
<view class='loading'> <view class='bg' wx:if="!transparent"> <image src='https://lg-gc2dnftu-1257370699.cos.ap-shanghai.myqcloud.com/timg.gif' width="100" height="100"></image> </view> </view>
調用頁面業務邏輯代碼:
1 Page({ 2 data: { 3 loading: false, //默認不顯示loading 4 transparent: false //默認顯示loading加載圖標,設置爲true,則只有蒙板,看不到loading圖標 5 ... 6 }, 7 /** 8 * 調用微信小程序api的單擊事件 9 */ 10 clickEventRequestMpaPI: function() { 11 //調用服務器端api顯示loading 12 this.setData({ 13 disabled: true 14 }) 15 //調用服務器端api(請求方法已封裝) 16 http.paymentOrder(prams).then(data => { 17 if (data) { 18 //調用服務器端api關閉loading 19 self.setData({ 20 loading: false 21 }) 22 var d = data; 23 self.orderId = d.orderNo; 24 //發起微信支付 25 //調用微信支付api顯示透明無圖標的loading 26 self.setData({ 27 loading: true, 28 transparent: true 29 }) 30 wx.requestPayment({ 31 ... 32 'success': function(data) { 33 //4.1.1查詢支付結果 34 ...... 35 }, 36 'fail': function(err) { 37 console.log("requestPayment fail:::", err) 38 }, 39 'complete': function(res) { 40 //調用微信支付api關閉透明無圖標的loading 41 self.setData({ 42 loading: false, 43 transparent: false 44 }) 45 } 46 }) 47 } 48 }) 49 } 50 ... 51 })
原創專業博客,轉載請註明來源地址:http://www.javashuo.com/article/p-pzattzos-es.html