uni-app小程序无感登录逻辑实现

  1. 封装请求,此处只是demo

    // request.js
    function post(url,data) {
          
          
      return new Promise((resolve, reject) => {
          
          
        uni.request({
          
          
          url,
          data,
          success: res => {
          
          
            if (res.code === 99) {
          
          
    			// 登录过期
              // 跳转到首页
              uni.reLaunch({
          
          URL: '/pages/index/index'})
            } else {
          
          
              resolve(res)
            }
          }
        })
      })
    }
    
  2. 封装登录接口(demo)

    // login.js
    export async function myLogin() {
          
          
      return new Promise(() => {
          
          
        uni.login({
          
          
          code,
          success: res => {
          
          
            // 调服务端登录
            const result = await post('/login', {
          
          code: res.code})
         		// 登录后把token存到本地缓存
            uni.setStorageSync('token', result.token)
            // 更新vuex中的登录状态
            store.commit('setIsLogin', true)
            resolve(result)
          }
        })
      })
    }
    
  3. 调用

    // App.vue
    onLaunch() {
          
          
      this.init()
    },
    async init() {
          
          
      if (uni.getStorageSync('token')) {
          
          
        // 如果本地有token,不调登录,继续执行其他逻辑
      } else {
          
          
        // 调登录
      	await myLogin()
        init()
      }
    }
    // home.vue
    import {
          
           mapGetters } from 'vuex'
    export default {
          
          
    	computed: {
          
          
        ...mapGetters(['isLoginGetters']),
        isLogin() {
          
          
          return this.isLoginGetters
        }
      },
      watch: {
          
          
        // 由于小程序没有一套完善的路由机制,开发者无法拦截小程序启动后进入页面的行为,可能会进入页面后,还没有拿到全局登录状态,所以需要监听
    	isLogin: {
          
          
    	  handler(newVal, oldVal) {
          
          
             if (newVal) {
          
          
              // 登录成功后再继续执行当前页面其他业务逻辑
             }
          },
          immediate: true
       }
     }
    }
    
  4. 大部分情况下,进入小程序都是到首页。如果小程序中有部分页面是从扫码或点击分享卡片直接进来(例如店铺详情页),就需要执行以上监听登录态的逻辑。

  5. 需求:登录过期的处理优化

    回到步骤1

    uni.reLaunch({url: ‘/pages/index/index’})

    这句代码会在任何情况下、只要登录过期都跳转到首页,如果不想跳转,而是在当前页面无感重新登录后,继续当前页面的请求,那该怎么做呢?

    思路1:在封装的请求方法中维护一个请求过期的队列,重新登录后再依次从队列中取出来调用,但是调用完后应该如何继续执行原本页面上请求回调后的代码呢?

    思路2:登录过期时通过uni.getLaunchOptionsSync()得到path和query参数,然后传给reLaunch方法,但是这样需要判断小程序是正常点击跳转进入当前页面,还是通过分享或者扫码进入,并且会有一个跳转页面的动作,体验不好。

    思路3:在需要处理的页面onLoad或者onShow回调中通过getCurrentPages()拿到当前页面对象,并放到vuex中,在登录过期时调用页面对象的onLoad方法,并传入启动参数,代码如下:

    // store/index.js
    state: {
          
          
      currentPage: null
    }
    mutations: {
          
          
      setCurrentPage(state, currentPage) {
          
          
        state.currentPage = currentPage
      }
    }
    // 店铺详情页面 /pages/store/index
    export default {
          
          
      methods: {
          
          
        ...mapMutations(['setCurrentPage']),
        onShow() {
          
          
          const pages = getCurrentPages()
          this.setCurrentPage(pages[pages.length - 1])
        }
      }
    }
    // request.js
    if (res.code === 99) {
          
          
      // 登录过期
      const launchOptions = uni.getLaunchOptionsSync()
      if (launchOptions.path === 'pages/store/index') {
          
          
        store.state.currentPage && store.state.currentPage.onLoad(launchOptions.query)
      } else {
          
          
        // 跳转到首页
      	uni.reLaunch({
          
          URL: '/pages/index/index'})
      }
    } else {
          
          
      resolve(res)
    }
    

    这样当接口报出token过期时,无论在哪个页面(在需要的页面获取getCurrentPages存到vuex),都可以做到无感重新登录,并且登录成功后继续页面的请求逻辑。

猜你喜欢

转载自blog.csdn.net/xinTianou123/article/details/126062883