微信小程序開發——點擊防重的解決方案

對於一些涉及後端接口請求的單擊事件,不論後端是否作了請求限制,前端仍是有必要進行點擊防重處理的。前端

這樣既能減小對服務器端的壓力,也能有效防止因重複請求而形成一些不可預期的異常。小程序

尤爲是接口請求結果處理的邏輯中有須要調用小程序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 方法再增長一個鎖定時間的參數,這樣使用起來更靈活,能夠知足不一樣需求。

相關文章
相關標籤/搜索