微信小程序開發遇到的那些坑

1、Webview內嵌H5頁面不可使用微信支付

最近在作公司的小程序項目時,須要作一個充值頁面,打算直接複用微信公衆號上已經開發好的H5頁面,誰知在本地真機調試的時候調到H5頁面可以支付成功,可是提到體驗版和正式版後發現不能調起微信支付,最後查了不少文檔發現小程序的web-view不支持微信支付,只能經過跳回小程序調用小程序支付的API。實現大致思路:在H5頁面獲取支付參數,而後判斷是否在小程序環境中,若是在,獲取到支付參數後返回到小程序並將支付參數傳給小程序,小程序調用wx.requestPayment(OBJECT)接口完成支付,須要注意的是,獲取支付參數的appId爲小程序的appId.下面是個人實現方式:html

  1. 在H5頁面引入JSSDK 1.3.2,判斷小程序環境,獲取支付參數,將支付參數返回給小程序,這裏須要注意的是「package」參數,由於其包含「=」,所以傳的時候注意使用encodeURIComponent編碼,獲取後decodeURIComponent解碼
  2. 在小程序新建一個空白page,在onLoad中獲取參數,獲取成功後發起微信支付請求
  3. 支付完成,處理相關邏輯

2、小程序獲取不到unionId

在小程序發佈到線上以後發現有些新用戶在登陸頁面卡死,最後發現是沒有獲取到unionId,爲何獲取不到unionId呢,看下微信對UnionId機制的原文解釋:
若是開發者擁有多個移動應用、網站應用、和公衆賬號(包括小程序),可經過unionid來區分用戶的惟一性,由於只要是同一個微信開放平臺賬號下的移動應用、網站應用和公衆賬號(包括小程序),用戶的unionid是惟一的。換句話說,同一用戶,對同一個微信開放平臺下的不一樣應用,unionid是相同的。
同一個微信開放平臺下的相同主體的App、公衆號、小程序,若是用戶已經關注公衆號,或者曾經登陸過App或公衆號,則用戶打開小程序時,開發者能夠直接經過wx.login獲取到該用戶UnionID,無須用戶再次受權。
注意: 後邊這句話的描述
用戶關注過公衆號,或者曾經登陸過App或公衆號,則用戶打開小程序時,開發者能夠直接經過wx.login獲取到該用戶UnionID
即:若是用戶沒有關注過公衆號,或者沒有登錄過App,經過wx.login是沒法獲取到該用戶UnionID,只能經過wx.getUserInfo來獲取UnionId
經驗證,系統不存在UnionId的小程序用戶都是沒有關注公衆號或未在App中使用微信受權的用戶
解決方案:
獲取小程序UnionId獲取不到時,wx.getUserInfo能夠獲取敏感數據,其中包含UnionId字段。
實現:參考https://www.cnblogs.com/cai-r...連接描述web

3、掃普通連接二維碼打開小程序

(使用該功能,小程序必須已是已發佈狀態)小程序提供了掃描普通二維碼跳轉小程序的功能,首先在微信公衆平臺配置二維碼規則,域名路徑必須是校驗文件所在路徑,能夠配置測試連接進行測試,能夠配置最多5個測試連接,能夠指定測試連接打開的測試範圍(開發、測試、正式),必須是具備體驗權限的用戶才能夠進行測試,非體驗用戶進入正式版本。規則發佈後,配置符合規則的連接都可進入到小程序。json

4、可拖拽元素趕上canvas二維碼

小程序官方組件movable-area、movable-view說明canvas

剛開始作這個可拖拽元素的時候,是準備將其作成一個組件,在每一個須要的地方引入便可,可是有一個很大的問題就是所在頁面有一個canvas生成的二維碼,原生組件在小程序中的層級是最高的,即無論怎麼佈局或者給z-index都是不生效的,因此拖拽元素拖拽過程當中會在二維碼下面。
解決這個問題的過程當中遇到了不少坑,首先想到的是小程序中有沒有直接生成二維碼圖片的插件,有是有,可是個人字符串太長了,生成的base64編碼均太長了,因此我仍是用的weapp-qrcode.js插件,這個插件自帶導出圖片的方法,用的就是wx.canvasToTempFilePath將畫布導出生成圖片,頁面上canvas所在位置放置一個image組件,將canvas移到可視區域外面,可是生成的圖片一直是亂的,原來是我沒給canvas樣式的高度和寬度致使生成出現問題,可是這樣仍是在一些安卓機上出現問題,調用wx.canvasToTempFilePath已是在draw回調以後了,可是仍是須要給延時才能夠,在這裏我給的500ms,基本上就能夠了。
原生組件層級最高的問題解決了,可是又出現一個問題,就是可拖拽元素是一個組件,所在頁面又有不少按鈕,若是直接將可拖拽組件的層級設置最高,那麼按鈕就不可點擊,若是不設置最高,那麼就不可拖拽了,有兩種方式能夠解決,一種是將按鈕以插槽的方式放在組件中,另外一種是不將拖拽元素寫成組件,之間將movable-area放在wxml的最外層,我採用的是第二種,若是每一個按鈕都寫成插槽的話維護起來太麻煩了小程序

5、微信小程序緩存-------緩存時效性

/**
 * 數據緩存沒有設置有效期
 */
class Storage {
  /**
   * 獲取緩存
   * @param String $key  key
   * @param String $def  若想要無緩存時,返回默認值則get('key','默認值')(支持字符串、json、數組、boolean等等)
   * @return value;
   */
  get(key, def = '') {
    const timeout = parseInt(wx.getStorageSync(`${key}__separator__`) || 0);

    // 過時失效
    if (timeout) {
      if (Date.now() > timeout) {
        this.remove(key);
        return;
      }
    }
    let value = wx.getStorageSync(key);
    return value ? value : def;
  }
  /**
   * 設置緩存
   * @param String $key       key
   * @param String $value     value(支持字符串、json、數組、boolean等等)
   * @param Number $timeout   過時時間(單位:分鐘)不設置時間即爲永久保存
   * @return value;
   */
  put(key, value, timeout = 0) {
    let _timeout = parseInt(timeout);
    wx.setStorageSync(key, value);
    if (_timeout) {
      wx.setStorageSync(`${key}__separator__`, Date.now() + 1000 * 60 * _timeout);
    } else {
      wx.removeStorageSync(`${key}__separator__`);
    }

    return value;
  }

  remove(key) {
    wx.removeStorageSync(key);
    wx.removeStorageSync(`${key}__separator__`);
    return undefined;
  }
}
export {
  Storage
}

6、小程序跳轉另小程序遇到的坑(監聽返回)

場景:在跳轉另外一個小程序以前須要調用接口獲取跳轉所需參數,在另外一個小程序返回時須要從新調用接口或許參數。
問題:首先想到的是點擊跳轉的時候調用接口,以後wx.navigateToMiniProgram跳轉,將接口返回數據攜帶上,可是,這種不是用戶直接觸發的跳轉,微信不支持。。。
而後,那就先在頁面的onload事件中直接調用一次,而後再監聽另外一個小程序返回,再調用一次接口,文檔上寫的很明白,監聽App.onShow就行了,因而我在該頁面的onshow直接wx.onAppShow監聽場景值爲1038,可是!!!這裏遇到了巨坑,第一次返回,wx.onAppShow調用一次,第二次返回,wx.onAppShow調用兩次,第三次返回,wx.onAppShow調用三次,直接致使整個流程出問題了。。。
解決:思考了很久,決定不用wx.onAppShow監聽場景值的辦法,直接在該頁面直接定義一個變量,好比navigateToOther,默認爲false,跳轉成功後置爲true,而後在onshow裏判斷是否爲true,若是爲true,調用接口,將navigateToOther置爲false。完美解決!!!微信小程序

7、小程序H5頁面分享

H5頁面中的分享轉發按鈕不能直接分享給好友,只能用折中的方式來作,點擊H5頁面的分享按鈕時,彈出提示框,指向右上角的轉發按鈕,並經過wx.miniProgram.postMessage將所需信息發送給小程序,用戶點擊轉發按鈕時能夠經過bindmessage接收到消息
參考連接:小程序內嵌web-view之分享(2)數組

8、webview刷新

小程序嵌套H5頁面時,有時頁面在來回切換時須要刷新該H5頁面,可是微信未提供相關接口,可是能夠經過折中的方式來實現。緩存

首先,讓webview作條件渲染:微信

<web-view wx:if="{{url}}" src="{{url}}" />
data: {
    base_url: config.kalatong_base_url + '……',
    url: ''
  },

  /**
   * 生命週期函數--監聽頁面加載
   */
  onLoad: function(options) {
    let url = this.data.base_url + "#wechat_redirect"
    this.data.url = decodeURIComponent(url)
  },
  
  /**
   * 生命週期函數--監聽頁面顯示
   */
  onShow: function() {
    this.refreshWebview()
  },

須要刷新時,先把url設爲空,銷燬當前webview。而後再把url設爲當前值。以下:app

refreshWebview: function () {
    let tmpUrl = this.data.url;
    this.setData({
      url: ''
    });
    setTimeout(() => {
      this.setData({
        url: tmpUrl
      })
    }, 500);
  }

這樣即可以在不影響導航欄歷史的狀況下刷新頁面,也能夠是跳轉url。這裏setData以後,頁面內容的更新應該是異步執行的,所以咱們後一次修改url須要延時一小段時間,不然會出現error。猜想setData後頁面實際更新應該是在下一次的requestAnimationFrame,所以若是頁面徹底不卡頓可能16ms就能夠了,保險起見,我設了100ms。可是100ms也不保險,有些頁面會空白,最後置成500ms

相關文章
相關標籤/搜索