小程序的一些坑

概述

最近项目使用小程序的web-view把现有项目迁移到小程序里面去。有一些心得,记录下来供以后开发时参考,相信对其他人也有用。

通用

1.企业小程序需要把接口域名填入服务器域名,把web-view的网址域名填入业务域名,把小程序和运营的公众号绑定。

2.授权。

根据授权接口升级公告,无法使用 wx.getUserInfo 接口直接弹出授权框,但是wx.getUserInfo 接口仍旧可以使用。目前微信上的授权和登录一般有2种方式:

  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信息。示例代码如下:

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 对 组件无效

1.web-view 里面的项目可以通过判断 userAgent 中包含 miniProgram 字样来判断小程序 web-view 环境(微信7.0.0以上)。示例代码如下:

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

2.不能在web-view里面打开新窗口,所以在项目上需要判断小程序环境,在需要新窗口打开的时候变成本窗口打开。

3.分享

在有 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>
原文地址:https://www.cnblogs.com/yangzhou33/p/10723134.html