《小程序成长记》登录用户篇(一)

405 阅读4分钟

距离上次用 mpvue 开发小程序已经过去了...好多年了吧。这次重拾小程序开发真真切切比对了一波市面上的框架。最终因为开发需求(无需跨平台开发)和痛点(懒得学习)还是选择了原生开发。接下来当然会不定时更新可能会违反广告法的小程序伪教程系列了。冲鸭!!!

webpack

当然原生 + webpack 讲道理也为所欲为了。

  • css 预编译
  • es6 (开发者工具本身支持)
  • alias
  • eslint
  • 代码压缩(开发者工具本身支持)
  • babel(暂时没有自己写插件的场景)

当然这里的多文件入口有点难顶,可以借鉴大佬的例子。所谓人前摇扇醒目拍桌,各位看官且...你且自行传送门好吧...手把手教你撸一个小程序 webpack 插件

一些概念

逐渐忘记标题才是最为致命的...

这里有些主观的理解提一下。小程序中登录模块和用户模块本是风马牛不相及(废话)。他们不相及的点是因为你需在认知上不混为一谈才能在代码中区分出来。好像有点解释不清的亚子,问题不大,上图。

可能此时看完图的你就会觉得这就尼玛离谱。图糙理不糙真的就只是调接口后 set 而已。

问题不大,我再挣扎解释一波。

登录

在调用 wx.login 后拿 code 跟后端带锅换取 openId session_key 之类的。这里很和谐的一个点就是,整个过程是无感登录的。你拿 code,再之后跟后端带锅拿的登录信息都是无需用户感知的。即是随风入夜,妙啊。

当然这里有几个场景光说不练傻把式,还是得代码铺一下的。

  • 第一次进入小程序当然要 wx.login
  • 调用后端接口登录信息失效时(token 失效)当然要wx.login
  • session_key 失效时当然要 wx.login

细心的阿弟应该留意到,后端带锅返回的字段中有 openId session_key UnionID(这里具体的字段解释可以官网了解 传送门)。其中我们会在 onLaunch 时判断 session_key 主动出击查看登录是否失效。(并不会每次进入小程序都执行登录,而是在失效时才登录)

  onLaunch() {
    const loginFlag = getStorage('session_key')
    if (loginFlag) {
      // 检查 session_key 是否过期
      wx.checkSession({
        // session_key 有效(未过期)
        success: function() {
          // 业务逻辑处理
          this.getUserInfo()
        },
        // session_key 过期
        fail: function() {
          // session_key过期,重新登录
          this.doLogin()
        }
      })
    } else {
      // 无session_key,作为首次登录
      this.doLogin()
    }
  },

另一个场景即是后端待锅告诉我们接口失效时的被动出击了。

请求拦截

众所周知,在 token 失效时后端带锅会返回约定好的状态码告知你接口失效。老实人只能乖乖重新 wx.login 了。这里安利一波 flyio拦截

请求拦截器和响应拦截器都提供了锁定自身的API, 拦截器锁定后,未进入到该拦截器的请求将在拦截器外面排队,暂停网络请求,直到拦截器解锁时,排队的请求才再次进入拦截器继续请求。

在接口登录失效后,加锁,后续请求入队。执行 wx.login 之后解锁。出队。

啧啧啧,妙蛙...种子啊...

const fly = new Fly()
const newFly = new Fly()

const login = (isAfresh) => new Promise((resolve, reject) => {
  wx.login({
    success: res => {
      (isAfresh ? newFly : fly).get(`/v1/miniapp/login/${res.code}`)
        .then((data) => {
          setStorage(data)
          resolve(data)
        })
        .catch((err) => {
          reject(err)
        })
    }
  })
})

fly.interceptors.response.use(
  ({ data, request }) => {
    wx.hideLoading()
    if (data.code !== ERR_OK) {
      // code = 1200 登录信息失效,重新login后再次调用本次接口
      if (data.code === 1200) {
        fly.interceptors.request.lock()

        return login('afresh')
          .finally(() => {
            fly.interceptors.request.unlock()
          })
          .then(() => {
            return fly.request(request)
          })
      } else {
        wx.showToast({
          title: data.msg,
          icon: 'none'
        })

        return Promise.reject({ message: data.msg })
      }
    } else {
      return data.data
    }
  }
)

至此,通过请求拦截和 onLaunch 主动判断 session_key,已然无敌。

用户信息

市面上获取用户信息方式千千万。微信官网推荐的交互体验为大部分页面均可浏览,部分操作则需要获取用户信息或才能操作。安排。

大体上,在特定操作上做一个 用户信息拦截 验证即可。这里我直接参考(拷贝)了 撸一个小程序前置授权组件 的方案。

<!--Authorization-->
<view class="wrapper m-class">
  <view bind:tap="handleTap">
    <slot></slot>
  </view>
  <block wx:if="{{!authorized}}">
    <button class="auth" open-type="{{openType}}" bindgetphonenumber="getPhoneNumber" bindgetuserinfo="getUserInfo"></button>
  </block>
</view>

如图,在组件上通过 css 覆盖点击区域,通过发布订阅模式监听是否授权。

更多 js 代码就不贴了,还是建议大家参考下授权组件的方案。

流程

那么,登录和用户授权就真的风马牛不相及么?

...咱也不造哇

但流程上必然还是你来我往的,手痒,我还是再苟一波流程图先。

参考