vue3+pinia用户信息持久缓存(token)的问题

vue3+pinia用户信息持久缓存(token)的问题

对博主来说,这是个相当复杂的问题。

当初在使用vue2+vuex进行用户信息持久登录时,写了不下3篇博客,确实是解决了问题,博客链接如下

第一篇博客是记录前端如何使用token,简言之,就是先把后端传过来的token写入到浏览器的localstorage缓存中,前端在处理路由之前,先检查localstorage中有没有token,有token就放行,没有token就跳转到登录界面

第二篇博客是发现token过期后的处理方式,最后我的vue2项目都没有使用这篇博客中的解决方案,而是使用了第三篇博客的解决方案

第三篇博客出现的问题是,**每次刷新页面,store里面的数据没了,而localstorage中还有数据,**这样的话,页面上有些地方需要store的数据就加载不出来了,但token并没有更新,出现了逻辑错误。解决方案就是每次在启动页面的时候,检查一下localstorage中有没有数据,有数据的话,重新设置一下store,当然,在路由守卫环节也添加了路由的放行规则

我把第三种方案当做终极解决方案,确实很长一段时间都没有再受到困扰

知道我现在开始使用vue3+pinia来写前端项目,问题又来了

pinia和vuex遇到的问题是一样的,我尝试用第三篇博客来解决,按道理应该是可以解决的,但实际上一直没能解决。折腾很长一段时间,找到了一种比较折中的解决方案

pinia-plugin-persistedstate持久化存储数据

实际上就是使用这个pinia-plugin-persistedstate插件,它解决的问题是,帮你把store中的数据持久化的存储在localstorage中,并且比较好的一点是,当你需要使用store中的数据时,它又从localstorage中取出来给你去渲染页面,其实就和我上面第3篇博客的内容差不多,这样就不怕刷新页面了,先来看看怎么写和怎么中

store文件的写法

直接看代码:

import {
    
     ref } from "vue";
import {
    
     defineStore } from "pinia";
import {
    
     loginAPI } from "@/apis/user";

export const useUserStore = defineStore(
  "user",
  () => {
    
    
    const userInfo = ref({
    
    });
    const getUserInfo = async (data) => {
    
    
      const res = await loginAPI(data);
      // console.log(res);
      userInfo.value = res;
      // console.log(userInfo.value)
    };
    //   解决刷新页面丢失store信息的问题
    const clearUserInfo = () => {
    
    
      userInfo.value = {
    
    };
      localStorage.removeItem('user')
    };
    return {
    
    
      userInfo,
      getUserInfo,
      clearUserInfo,
    };
  },
  {
    
    
    persist: true,
  }
);

pinia用的组合式api写法

  • userInfo是用户信息
  • getUserInfo是通过调用登录接口,修改userInfo
  • clearUserInfo是清除用户信息

在代码的最后面,加了个对象persist: true,之后每次登录,就会在localstorage中生成一个key为user的字符串对象,刷新页面而这个对象不会消失,模板上需要渲染的时候,又把内容添加给store,相对来说比较靠谱。命名规则就是definstore时定义的变量名。

在我没有添加路由守卫规则之前,这么写的话,会有个问题,退出登录后,还能返回到原来的路由,只是页面上该有的用户信息都没有了,因为clearUserInfo并没有删除localstorage中的user对象,user一直都在,那按照之前的逻辑,当然行不通了

退出登录时的操作

看看具体怎么解决吧

//这是退出登录用到的方法
const logout = () => {
    
    
    // userStore.clearUserInfo()
    localStorage.removeItem('user')    
    router.push('/login')
}

其实就是清除localstorage中的user对象

路由守卫

路由守卫是最麻烦的地方,逻辑理不清楚,就没法正常跳转

我的写法

// 路由守卫
import jwt_decode from "jwt-decode";
router.beforeEach((to, from, next) => {
    
    
  const isLogin = localStorage.user ? true : false;
  if (isLogin) {
    
    
    const user = JSON.parse(localStorage.user)
    const decode = jwt_decode(user.userInfo.token);

    const date = parseInt(new Date().getTime() / 1000);

    if (date - decode.iat > decode.exp - decode.iat) {
    
    
      localStorage.removeItem("user");
      next("/login");
    }
  }

  if (to.path == "/login") {
    
    
    next();
  } else {
    
    
    isLogin ? next() : next("/login");
  }
});

还是根据localstorage中是否有user对象来判断是否登录,但是前面说过了,它存在localstorage中的是一个字符串,大体是下面这个样子

image-20230706141113934

可以看出来,里面有你定义的state数据,所以,需要解析先成json才能正常取值,取值后,就是解析其中的token了,解析完token,就可以判断有没有过期来清除token了

总之,过程相当繁琐,希望不要再写第5篇了。

猜你喜欢

转载自blog.csdn.net/u012848304/article/details/131575678