Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

小程序的一些坑 #30

Open
sishenhei7 opened this issue Apr 17, 2019 · 0 comments
Open

小程序的一些坑 #30

sishenhei7 opened this issue Apr 17, 2019 · 0 comments
Labels

Comments

@sishenhei7
Copy link
Owner

概述

最近项目使用小程序的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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant