个人博客——路由守卫、pinia持久化、全局请求加载动画

设置路由守卫

登录后会根据不同角色跳转到前台或后台页面。也直接通过修改访问路径的方式访问后台,这显然是不安全的,因此需要设置路由守卫,在进行路由跳转前判断该用户是否可以跳转到该页面
在src\router\index.ts中加入下面的代码片段。路由白名单中是不需要验证直接放行的页面,在白名单之外的路径则获取当前用户的token和角色,已经登录且是管理员才能继续,否则进入登录页。

//路由白名单
const whiteRouters = ['/','/toLogin',]

//路由守卫
router.beforeEach((to, from, next) => {
  //如果在白名单中直接放行
  if (whiteRouters.indexOf(to.path) != -1){
     return next();
  }else{
    //否则获取当前用户的token和角色
    const userMsg = userStore();
    const token = userMsg.userToken;
    const role = userMsg.userRole;
    //已经登录且是管理员才能继续,否则进入登录页
      if (token == '' || role != 1){
       return next('/toLogin')
      }else{
         next();
      } 

  }

需要注意的是,const userMsg = userStore();如果写在全局守卫之外会报以下错误,

Uncaught Error: [🍍]: “getActivePinia()” was called but there was no
active Pinia. Did you forget to install pinia? const pinia =
createPinia()

这个错误好像是因为pinia没有激活引起的,应该是使用userStore时pinia为创建,如果想在全局守卫之外写,可以参考这篇文章的第二种解决方法,但是第二种方法会影响pinia持久化插件的使用,推荐使用第一种方法。

pinia持久化

将数据保存到pinia中后,发现一个问题,就是刷新之后数据会丢失。
像这样,保存在pinia中的token刷新后丢失了。
在这里插入图片描述
这里通过使用插件pinia-plugin-persistedstate完成数据持久化

  1. npm i pinia-plugin-persistedstate 下载安装
  2. 在main.ts中使用
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

export const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);

createApp(App).use(router).use(pinia).use(ElementPlus).mount('#app')
  1. 在需要持久化的仓库中加入{ persist: true,}
    例如
export const userStore = defineStore('user',()=>{

    //token的存储和处理
    const userToken = ref('');
    const userRole = ref(0);

   const setData = (token:string,role:number)=>{      
         userToken.value = token;
         userRole.value = role;
    }
    
    return {userToken,setData,userRole}
   },
   {
    persist: true,
  }
)

至此,pinia的数据持久化就完成了,效果如下所示
在这里插入图片描述
通过以上方式,会将数据保存在localStorage中
在这里插入图片描述
也可以通过配置persist的属性storage,存到sessionStorage中。

export const userStore = defineStore('user',()=>{

    //token的存储和处理
    const userToken = ref('');
    const userRole = ref(0);

   const setData = (token:string,role:number)=>{      
         userToken.value = token;
         userRole.value = role;
    }
    
    return {userToken,setData,userRole}
   },
   {
   //存在sessionStorage
    persist: {
     storage: sessionStorage,
     }
   }  

)

还可以通过配置其他属性达到存储指定数据的效果
详情见文章
也可以看视频
本文pina的持久化主要参考上面这两个链接。

全局请求加载动画

设置全局加载动画,发起请求时显示加载动画,请求结束关闭加载动画,并对同时进行的多个请求进行合并。

  1. 在utils文件夹添加loading.ts,存放展示加载动画和隐藏加载动画的相关方法。代码如下
/**
 * 全局loading效果:合并多次loading请求,避免重复请求
 * 当调用一次showLoading,则次数+1;当次数为0时,则显示loading
 * 当调用一次hideLoading,则次数-1; 当次数为0时,则结束loading
 */
import { ElLoading } from 'element-plus';
 
// 定义一个请求次数的变量,用来记录当前页面总共请求的次数
let loadingRequestCount = 0;
// 初始化loading
let loadingInstance:any;
 
// 编写一个显示loading的函数 并且记录请求次数 ++
const showLoading = () => {
    if (loadingRequestCount === 0) {
        // element的服务方式 target 我这边取的是表格class
        // 类似整个表格loading和在表格配置v-loading一样的效果,这么做是全局实现了,不用每个页面单独去v-loading
        loadingInstance = ElLoading.service({ 
            lock:true,    //是否锁定
            text:"拼命加载中...",   //显示在加载图标下方的加载文案
            background:'rgba(0,0,0,.7)',   //遮罩背景色
         });
    }
    loadingRequestCount++
}
 
// 编写一个隐藏loading的函数,并且记录请求次数 --
const hideLoading = () => {
    if (loadingRequestCount <= 0) return
    loadingRequestCount--
    if (loadingRequestCount === 0) {
        loadingInstance.close();
    }
 }
 
 export {
    showLoading,
    hideLoading
 }
  1. 在utils\request.ts中使用

import axios, {AxiosInstance,AxiosRequestConfig,AxiosResponse,AxiosError} from 'axios'
import { ElMessage } from 'element-plus'
import {showLoading,hideLoading} from './loading'



// 数据返回的接口
// 定义请求响应参数
interface Result<T> {
  code: number;
  msg: string;
  data?: T;
}

const config = {
  // 默认地址
  baseURL: "http://localhost:8080",
  // 设置超时时间
  timeout: 3000,
  // 跨域时候允许携带凭证
//   withCredentials: true
}

class Request {
  // 定义成员变量并指定类型
  service: AxiosInstance;
  public constructor(config: AxiosRequestConfig) {
   // 实例化axios
   this.service = axios.create(config);

    /**请求拦截器
    */
   this.service.interceptors.request.use(  
     //这里的config声明为AxiosRequestConfig类型会报错,很奇怪
     (config: any) => {
      // 发起请求时开始Loading
         showLoading();
         ........
     },
     (error: AxiosError) => {
      // 请求报错
      Promise.reject(error)
     }
    )
     
    /**
     * 响应拦截器
     */
    this.service.interceptors.response.use(
      (response: AxiosResponse) => {
        /*
         获得响应后关闭Loading
         采用延时处理是合并loading请求效果,避免多次请求loading关闭又开启
         */
        setTimeout(() => {
          hideLoading()
        }, 200); 
         ........

      },
      (error: AxiosError) => {
        setTimeout(() => {
          hideLoading()
        }, 200);
        .............
       }
      }
    )

  }
}

// 导出一个实例对象
export default new Request(config);

到此,全局请求加载动画配置完成,效果如下

在这里插入图片描述

全局请求动画配置参考文章

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值