CSS微信小程序的坑边杂谈

小程序微信登录

2019-04-09  本文已影响174人  国王不在家

相信大家做小程序的, 对微信登录的机制都有一定的了解以及想法了;
大家八仙过海 各显神通,下面这篇文章,只是我对其的了解
如果大家有好的想法 !!!请一定 与 我交流!!!

I、处理登录的逻辑

关于会遇到的问题以及处理

  1. 首先请求是个异步事件,我们并不是所有接口都需要登录;
    既然是异步事件, 那么我们肯定要在回调函数中进行处理
    这样的话就要涉及到wx.request的封装;我们在下面讲
  2. 关于code的获取
    登录需要用户点击微信自带的button才能获取到
    <button class='login-btn' open-type="getUserInfo" bindgetuserinfo="getUserInfo" 
    type="warn" size="default" loading="{{loading}}" bindtap="primary"> 
        一键登录 
    </button>
  1. 关于权限判断,以及如何判断
    咱们不能所有接口都需要登录, 那样的话连审核都过不了;
    这里同样需要对wx.requesrt进行封装;下面讲

  2. 登录的处理逻辑图:

    小程序登录逻辑.png

II、wx.request的封装逻辑

1. wx.request的封装

  1. 基础层
    a. 调用扩展层的处理函数
    b. wx.request请求

  2. 扩展层
    beforeRequest 发起请求之前 处理有无网络状态
    handleRequestInportData 处理请求参数
    showMask 处理遮罩层
    stopLoading 停止各种的loading
    handleResponse 处理返回结果 (在这里面处理是否跳转登录)

2. wx.request的封装逻辑图

小程序request请求封装.png

III、关于登录 对wx.request的封装

当然是写在handleResponse里面的
跟后端约定好返回码 做对应的操作;
我们这边规定 如果返回 code == 401 || code == 403的话就表示没有登录

if (res.data.code == '401' || res.data.code == '403') {
      console.error('没登录,去登录,并且设置状态')
      // 清空之前的token
      wx.removeStorageSync('accessToken');      
      // 正在登录中
      if (that.globalData.isLogging) return true;   
      // 没在登录中 进入登录状态,并且设置isLogging 
      that.globalData.isLogging = true;     
      // 登录失效且不在白名单 
      if (!CONFIG['API_WHITE_LIST'].includes(thisUrl)) {
        // 跳到登录
        let pages = getCurrentPages();
        for (let i in pages) {
          if (pages[i].route == '/pages/login/login') {
            // console.log(i)
            wx.navigateBack({
              delta: pages.length - (i + 1)
            })
            return true;
          }
        }
        wx.navigateTo({ url: '/pages/login/login' });
        return true;
      }
      return;
    }

IV、相关代码

1. wx.request关于基础层的封装

// 基础层: 
  // 基于微信的request进行二次封装,myRequest是基础层
  // beforeRequest 处理有无网络状态
  // handleRequestInportData 处理请求参数
  // showMask 处理遮罩层
  // stopLoading 停止各种的loading
  // handleResponse 处理返回结果
  
  myRequest: function (url, data, methods, callback, loadType, errorFun, headers) {
    let _this = this;
    // 检查是拥有网络 没有网络 就return;
    if (_this.beforeRequest(url)) return;
    // 参数处理
    let theData = this.handleRequestInportData(url, data, methods, callback, loadType, errorFun, headers, _this);
    // 处理遮罩层
    this.showMask(theData.loadType);

    // 是否是启用模拟数据
    if (DEBUG) {
      let responseData = myData.getData(url, data);
      setTimeout(() => {
        console.log('DEBUG response : ')
        console.log(responseData.data)
        _this.stopLoading();
        callback(responseData)
        // _this.handleResponse(responseData, theData);
      }, 800)
    }else{
    // 开始请求
      wx.request({
        url: theData.url,
        data: {
          ...theData.data,
          ..._this.globalData.otherParams
        },
        method: theData.methods,
        header: theData.headers,
        success: function (res) {
          // 处理返回结果
          _this.handleResponse(res, theData, _this, url);
        },
        fail: function (err) {
          _this.stopLoading();
        },
        complete: function () {
        }
      })
    }
    // 请求结束
  },

2. wx.request 扩展层的封装


// 在请求发起之前需要做的事情 处理有无网络状态
  beforeRequest: function(tempUrl) {
    let _this = this;
    wx.getNetworkType({
      success: function (res) {
        if (res.networkType == 'none') {
          return true;
        }
      }
    })
  },

  // 处理请求参数:
  handleRequestInportData: (
    url,
    data,
    methods = 'post',
    callback = () => console.log('未传入回调callback'),
    loadType = 'mask',
    errorFun = (err) => {
      wx.hideLoading();
      wx.showToast({
        title: err.message,
        icon: 'none',
        mask: true,
        duration: 2000
      })
      console.log('未传入回调 errorFun')
    },
    headers = {},
    that
  ) => {
    let requestData = {};
    if (!url) {
      console.error('传入myRequest的URL不可为空');
      return;
    }
    headers = {
      'content-type': 'application/json',
      'Authorization': 'Bearer ' + that.globalData.accessToken,
      'enctype': 'raw'
    }
    data.referrer_uid = that.globalData.referrer_uid != 0 ? that.globalData.referrer_uid : 0;

    requestData.url = InterFace[url];
    requestData.data = data;
    requestData.methods = methods;
    requestData.callback = callback;
    requestData.loadType = loadType;
    requestData.errorFun = errorFun;
    requestData.headers = headers;
    return requestData;
  },



  // 处理返回结果:
  handleResponse: (res, theData, that, tempUrl) => {
    let _this = this;
    that.stopLoading();
    if (res.data.code == '401' || res.data.code == '403') {
      console.error('没登录,去登录,并且设置状态')
      // console.error(that.globalData.isLogging)
      wx.removeStorageSync('accessToken');
      // 正在登录中 设置 isLogging
      if (that.globalData.isLogging) return true;
      that.globalData.isLogging = true;
      // 登录失效且不在白名单 !wx.getStorageSync('accessToken') && !API_WHITE_LIST.includes(tempUrl)
      if (!CONFIG['API_WHITE_LIST'].includes(tempUrl)) {
        // 跳到登录
        let pages = getCurrentPages();
        // Tips: 判断页面栈中是否有login
        for (let i in pages) {
          if (pages[i].route == '/pages/login/login') {
            wx.navigateBack({
              delta: pages.length - (i + 1)
            })
            return true;
          }
        }
        wx.navigateTo({ url: '/pages/login/login' });
        return true;
      }
      return;
    }
    if (res.data.status == 200 && res.data.code != 0) {
      // 调用错误处理函数
      theData.errorFun(res.data)
      return;
    } else if (res.data.code == '503' || res.data.code == '500') {
      // 故障页面
      wx.reLaunch({
        url: '/pages/error/error'
      })
      return;
    }
    // 正常情况下, 回调
    if (res.data.status == 200 && res.data.code == 0) {
      theData.callback(res.data);
      return;
    }
  },


  // 展示遮罩层:
  showMask: (loadType) =>{
    if(loadType == 'none') return;
    if(loadType == 'top'){
      wx.showNavigationBarLoading()
      return;
    }
    wx.showLoading({
      title: '加载中',
      mask: true,
    })
  },
  

  /*
  * 停止各种loading状态
  * @function stopLoading
  * @params {}
  * @barth {Constantine, 2017-11-13 17:19:15}
  */
  stopLoading: () => {
    wx.hideLoading();
    wx.hideNavigationBarLoading()
    wx.stopPullDownRefresh()
  },

3. 登录页面代码

<!--pages/login/login.wxml-->
<nav title="选择登录方式"></nav>
<view class='cul-null'>抱歉您还未登录呢, 请点击下方授权按钮登录</view>
<view class='cul-null'>以使用更多功能</view>

<button class='login-btn' open-type="getUserInfo" bindgetuserinfo="getUserInfo" type="warn" size="default" loading="{{loading}}" bindtap="primary"> 一键登录 </button>
<button class='login-btn' plain="{{true}}" type="default" size="default" bindtap="jumpTo" data-url='/pages/loginOld/loginOld'> 手机登录 </button>
// pages/login/login.js
   /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {
    app.globalData.isLogging = false;
  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
    app.globalData.isLogging = false;
  },
  
  // 发起登录
  getUserInfo: function (e) {
    console.log(e)
    this.setData({
      loading: true
    })
    let encryptedData = e.detail.encryptedData;
    let iv = e.detail.iv;

    console.log('login in')
    let _this = this;

    wx.login({
      success: ret => {
        // 发送 res.code 到后台换取 openId, sessionKey, unionId
        var CODE = ret.code;
        app.globalData.otherParams.wxcode = ret.code;
        app.myRequest('login', {
          wxcode: CODE,
          info: e.detail.userInfo,
          allInfo: e.detail,
        },
          'get',
          function (data) {
            console.log(data)
            if(data.data.has_reg == false){
              _this.userRegister(encryptedData, iv, data.data.openid)
              console.error('没有注册过')
            }else{
              console.error('注册过')
              wx.showToast({
                title: '已有账号,登录中',
                icon: 'none',
                mask: true,
                duration: 1500
              })
              _this.saveData(data);
              _this.setData({
                loading: false,
                userInfo: data.data.memberProfile,
                hasUserInfo: true
              })
              if (!data.data.has_phone){
                // TODO: 判断用户有没有手机号,没有调用接口绑定,并且完善密码
              }
              setTimeout(() => {
                wx.navigateBack({
                  delta: 1
                })
              }, 800)
            }
          })
        console.log('login', ret)
      }
    })
  },

  // 自动注册
  userRegister: function (encryptedData, iv, openid) {

    let _this = this;
    app.myRequest('userRegister', {
      encryptedData: encryptedData,
      iv: iv,
      openid: openid
    },
      'post',
      function (data) {
        console.log(data)
        // 缓存数据
        _this.saveData(data);
        _this.setData({
          userInfo: data.data.memberProfile,
          member: data.data.member,
          hasUserInfo: true,
          hideBindBlock: false,
          loading: false
        })
        app.globalData.newUser = true;
        wx.showToast({
          title: '注册成功',
          icon: 'none',
          mask: true,
          duration: 1500
        })
      })
  },

4.关于登录按钮的样式

不满意的话你可以让微信自带的buttom opacity = 0
然后自己写一个想要的样式放在自带的buttom的下面

结束语

能坚持到这里的已经是真爱了
希望各位大神 有好的方法 与我交流🔚

上一篇下一篇

猜你喜欢

热点阅读