微信小程序mpvue+vantUI+flyio+vuex入坑(3)

1,402 阅读3分钟

很久之后才更新,一个是比较忙,还有就是不知道还要介绍啥,最近有小伙伴问我,怎么鉴权之类的,我就分享一下我的鉴权。

项目结构

先看看项目结构

  ├── build           # webpack文件,配置参数,打包的代码存放在这里。
  ├── config          # vue项目的基本配置文件
  ├── node_modules    # 项目中安装的依赖模块
  ├── src             # 源代码文件夹
      └── api         # 请求接口文件
      └── components  # 放置各个vue组件文件
      └── pages       # 各个页面文件
      └── store       # 项目的状态管理文件,包括登录,用户信息和token等
      └── style       # 项目公共样式
      └── utils       # 项目公用的js文件
      └── app.json    # 小程序的app.json
      └── App.vue     # App.vue组件,项目入口文件
      └── main.js     # 项目的核心入口文件
  ├── static          # 静态资源目录,如图片、字体等
      └── images         # 登录加密配置文件
  ├── .babelrc        # babel编译参数,vue开发需要babel编译
  ├── .editorconfig   # 代码编辑环境配置文件
  ├── .eslintignore   # eslint检查忽略文件
  ├── .eslintrc.js    # eslint检查配置文件
  ├── .gitignore      # git提忽略文件
  ├── .postcssrc.js   # css配置文件,自动补齐浏览器css前缀
  ├── index.html      # 主页,项目入口文件
  ├── package.json    # 项目配置文件,,描述项目信息和依赖
  ├── README.md       # 项目的说明文档,markdown 格式

Vuex的使用

首先安装vuex

npm install vuex -S

创建store

创建好store目录后,和普通vue的项目一样,使用vuex

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    user
  },
  state: {
    count: 0
  },
  mutations: {
    increment: (state) => {
      const obj = state
      obj.count += 1
    },
    decrement: (state) => {
      const obj = state
      obj.count -= 1
    }
  }
})

export default store

将store挂载到Vue上

配置要做状态管理的内容

我的token信息就是存在user里,利用小程序的storage来做持久化

const user = {
  state: {
    token: mpvue.getStorageSync('token'),
    userinfo: mpvue.getStorageSync('user')
  },
  mutations: {
    SET_TOKEN: (state, token) => {
      state.token = token
    },
    SET_USER: (state, user) => {
      state.userinfo = user
    }
 }
}

和普通vue项目的使用完全一样
在template里直接$store.state.user.token就可以直接获取到,当然你也可以写getter来方便获取 在js里也是一样 this.$store.state.user.token 也是可以直接获取到
当然mapState也可以使用

import { mapState } from 'vuex'

export default {
  computed: {
    ...mapState({
      userinfo: state => state.user.userinfo
    })
  }
 }

配置apiconfig,请求数据的鉴权

首先引入store

import store from '@/store'

请求拦截

对请求进行拦截处理,这个之前讲flyio的时候也说过

// 添加请求拦截器
fly.interceptors.request.use(config => {
  const token = store.state.user.token
  // console.log(token)
  // 给所有请求添加自定义header
  config.headers['token'] = token
  if (config.headers['Content-Type'] !== 'application/json') {
    config.body = qs.stringify(config.body)
  }
  // 可以显式返回request, 也可以不返回,没有返回值时拦截器中默认返回request
  return config
}, error => {
  Promise.reject(error)
})

响应的鉴权拦截

因为小程序首次授权后,再次进入的时候可能会停留在上次进入的页面,如果这个时候token已经失效,应该不让用户知道,偷偷的登录

let reqCount = 0
// 响应拦截器
fly.interceptors.response.use(async response => {
  // 同意处理一些响应的code状态
  // do sthing
  // 只将请求结果的data字段返回
  console.log(response, response.request)
  // 判断是否有响应,与后台进行统一,如果是token失效过期之类的,就进入以下方法
  if (response.data && response.data.code === '00000') {
    // 重新登录,并且记录请求登录的次数,登录3次后仍失败,跳转到授权登录页面
    reqCount += 1
    if (reqCount < 3) {
        let data = await store.dispatch('wxLogin').then(async () => {
            // 登录成功后,重新发起之前的请求拿到数据,返回
            let res = await fly.request(response.request).then(res => res)
            reqCount = 0
            return res
        })
    } else {
        mpvue.redirectTo({
          url: '/pages/login'
        })
    }
    return data
  } else {
    return response.data
  }
},
(err) => {
  // 发生网络错误后会走到这里
  wx.getNetworkType({
    success: res => {
      console.log(res)
      if (res.networkType === 'none') {
        wx.showToast({
          title: '当前网络不可用,请检查你的网络设置',
          icon: 'none',
          duration: 2000
        })
      } else {
        wx.showToast({
          title: '服务器繁忙,请稍候再试',
          icon: 'none',
          duration: 2000
        })
      }
    }
  })
  console.log(err)
})、

小程序的授权判断

由于mpvue的进入都会从App.vue进入,所以我把授权写在App.vue里

mounted () {
    // 获取用户授权状态
    mpvue.getSetting({
      success: (res) => {
        // 如果没有授权的话,管他三七二十一,跳转到登录授权页面,让他去授权
        if (res.authSetting['scope.userInfo'] === undefined) {
          if (this.$router.currentRoute && this.$router.currentRoute.path !== '/pages/login') {
            mpvue.navigateTo({
              url: '/pages/login'
            })
            return false
          }
        } else if (res.authSetting['scope.userInfo'] !== undefined && res.authSetting['scope.userInfo'] !== true) {
          console.log('拒绝授权')
        } else {
          // console.log('已授权')
          // 已经授权,就调后台的登录接口,进行登录
          this.$store.dispatch('wxLogin').then(() => {
            // 判断当前进行登录的动作发生的页面,如果是登录授权页,就跳转到首页,否则留在当前页面
            if (this.$router.currentRoute && this.$router.currentRoute.path === '/pages/login') {
              mpvue.switchTab({
                url: '/pages/index'
              })
            }
          })
        }
      },
      fail: res => {
        console.log(res)
      }
    })
  }