小程序的一些坑

概述

最近項目使用小程序的web-view把現有項目遷移到小程序裏面去。有一些心得,記錄下來供之後開發時參考,相信對其餘人也有用。html

通用

1.企業小程序須要把接口域名填入服務器域名,把web-view的網址域名填入業務域名,把小程序和運營的公衆號綁定。vue

2.受權。web

根據受權接口升級公告,沒法使用 wx.getUserInfo 接口直接彈出受權框,可是wx.getUserInfo 接口仍舊可使用。目前微信上的受權和登陸通常有2種方式:npm

  1. 比較通用,具備獨立的我的中心頁,每次打開我的中心頁都會向開發者服務器發送http請求,請求中有code,開發者服務器利用這個code向微信服務器獲取用戶數據來肯定用戶是否已經受權,若是沒有受權就須要用戶點擊受權按鈕,若是已經受權就順便傳回用戶頭像等信息。(這個方法適用於須要傳回用戶頭像等信息的場合)
  2. 沒有獨立的我的中心頁,也不須要開發者服務器傳回用戶頭像等信息,直接用 wx.getSetting 接口判斷用戶是否已經受權,沒受權則跳轉受權頁讓用戶點擊受權按鈕,已受權則走正常流程,示例代碼以下:
wx.getSetting({
  success: (settingRes) => {
    if (settingRes.authSetting['scope.userInfo']) {
      wx.showLoading({ title: 'Loading!' });
      wx.getUserInfo({
        success: (res) => {
          that.globalData.encryptedData = res.encryptedData;
          that.globalData.iv = res.iv;
          resolve(res);
        },
        fail: err => reject(err),
      })
    } else {
      // 未受權,跳轉受權頁
      wx.reLaunch({
        url: '../auth/index',
      });
    }
  },
  fail: err => reject(err),
})

3.接口封裝小程序

由於小程序使用的微信api都是回調形式的,而且很容易嵌套,引發回調地獄。因此通常須要使用promise進行封裝(若是要使用await的話,須要引入regenerator-runtime庫)。使用promise進行封裝還能利用catch很簡便的處理error信息。示例代碼以下:api

wxLogin: function () {
  const that = this;
  return new Promise((resolve, reject) => {
    wx.login({
      success: (res) => {
        that.globalData.loginCode = res.code;
        resolve(res);
      },
      fail: err => reject(err),
    });
  });
},
wxGetSetting: function () {
  const that = this;
  return new Promise((resolve, reject) => {
    wx.getSetting({
      success: (settingRes) => {
        if (settingRes.authSetting['scope.userInfo']) {
          wx.showLoading({ title: 'Loading!' });
          wx.getUserInfo({
            success: (res) => {
              that.globalData.encryptedData = res.encryptedData;
              that.globalData.iv = res.iv;
              resolve(res);
            },
            fail: err => reject(err),
          })
        } else {
          // 未受權,跳轉受權頁
          wx.reLaunch({
            url: '../auth/index',
          });
        }
      },
      fail: err => reject(err),
    })
  });
},
onLoad(options) {
  const that = this;
  this.handleUrlFromShare(options);
  app.wxLogin()
    .then(res => app.wxGetSetting())
    .then(res => that.requestCodeApi())
    .catch((err) => {
      wx.hideLoading();
      this.setData({
        isFirstLogin: true,
      });

      // 正常登錄
      if (err.hideToast) return;
      // 登錄失敗
      that.showErrorToast(err, 'Login Again Please!');
      console.log('Login failed-------', err);
    });
},

web-view組件的使用

小程序的web-view是承載網頁的容器,至關於iframe。它會自動鋪滿整個小程序頁面,我的類型與海外類型的小程序暫不支持使用,而且 navigationStyle: custom 對 組件無效 promise

1.web-view 裏面的項目能夠經過判斷 userAgent 中包含 miniProgram 字樣來判斷小程序 web-view 環境(微信7.0.0以上)。示例代碼以下:服務器

export function isMiniProgram() {
  return !!navigator.userAgent.match(/miniProgram/i);
}

2.不能在web-view裏面打開新窗口,因此在項目上須要判斷小程序環境,在須要新窗口打開的時候變成本窗口打開。微信

3.分享app

在有 web-view 的小程序頁面能夠利用 options.webViewUrl 拿到 web-view 裏面的網址,而後在分享的時候帶上這個網址,在跳轉頁面判斷是否有url參數來接收這個網址。

須要注意的是,

  1. 若是網址中有token等信息,須要先去掉這個信息。
  2. 若是網址中有漢字等符號,就須要使用encodeURIComponent轉義一下。
  3. 有些時候,可能須要雙重轉義才能拿到想要的url。

示例以下:

deleteTkAndRtk: function(url) {
  const host = url.slice(0, url.indexOf('?'));
  let queryArr = url.slice(url.indexOf('?') + 1, url.length).split('&');

  queryArr = queryArr.filter(
    query => query.indexOf('tk=') === -1 && query.indexOf('rtk=') === -1);

  if (queryArr.length !== 0) {
    return host + '?' + queryArr.join('');
  }

  return host;
},
onShareAppMessage: function (options) {
  const url = options.webViewUrl;
  const filteredUrl = this.deleteTkAndRtk(url);
  return {
    path: `pages/index/index?url=${encodeURIComponent(filteredUrl)}`,
    title: 'YiDrone',
  }
},
onLoad: function (options) {
  if (options.url) {
    this.setData({
      // 這裏的encodeURI必不可少。。。
      yidroneUrl: encodeURI(decodeURIComponent(options.url)),
    })
  }
},

4.jssdk

web-view中的項目能夠給小程序發送信息,還能夠控制小程序的頁面跳轉,方法以下:

// 首先在項目內引入 weixin-js-sdk 庫
npm install weixin-js-sdk --save

// 而後在plugin文件夾創建 wx-sdk.js
import Vue from 'vue';
import wx from 'weixin-js-sdk';

Vue.prototype.$wx = wx;

// 而後在main.js裏面判斷小程序環境按需引入 wx-sdk.js
// weixin-js-sdk
try {
  if (isMiniProgram()) {
    import('./plugins/wx-sdk').then(() => {});
  }
} catch (err) {
  console.error('>>>wx-sdk', err);
}

// 最後在須要的地方進行操做
if (isMiniProgram() && this.$wx) {
  // 不能使用這個格式:this.$wx.miniProgram.postMessage({ data: 'bar' });
  this.$wx.miniProgram.postMessage({ data: { foo: 'bar' } });
  this.$wx.miniProgram.navigateTo({ url: '../auth/index' });
}

// 在小程序的web-view組件加入 handleBindmessage 事件
<web-view src="{{ url }}" bindmessage="handleBindmessage"></web-view>
相關文章
相關標籤/搜索