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


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

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM