当前位置: 首页 > news >正文

vue3:九、路由守卫

官网参考:导航守卫 | Vue Router

一、Vue 路由守卫的作用

​1、权限控制

检查用户是否已登录,如果未登录则重定向到登录页面。

根据用户角色限制访问某些路由。

​2、数据预加载

在进入路由前加载必要的数据,确保页面渲染时有完整的数据。

3、​导航拦截

在某些条件下阻止用户离开当前页面(例如表单未保存时)。

​4、日志记录

记录用户访问的路由,用于分析或调试。

​5、动态路由

根据条件动态添加或修改路由。

二、根据路由守卫更改页面的名称

1、引入基本语法

首先输出一下to和from参数

//设置路由守卫
router.beforeEach((to, from, next) => {
  console.log('to', to)
  console.log('from', from)
  next()
})

可查看到一个参数meta.title,其可对标题名称进行修改

2、设置系统总标题

直接设置一个变量即可

//设置系统标题
const SystemTitle = 'SMS后台管理系统';

3、设置路径的标题

在之前设置的项中,设置meta下title的名称

只用设置外层页面的标题,主要的含导航内容的页面暂不修改

4、修改页面标题

修改页面的标题的方法为document.title

//设置系统标题
const SystemTitle = 'SMS后台管理系统';
//设置路由守卫
router.beforeEach((to, from, next) => {
  if(to.meta.title){
    document.title = to.meta.title + '-' + SystemTitle
  }
  next()
})

5、测试效果

三、权限控制

主要针对需要登录的页面,

  • 没有token
    • 在需要登录的页面-跳转登录页面
    • 不需要登录的页面-放行(可以继续执行)
  • 有token
    • 如果在登录页面-跳转到主页面
    • 如果没在登录页面-pinia读取用户信息

1、基本信息设置

首先获取token,查看token是否存在,如果不存在需要跳转到登录页面

①引入token获取

import { getToken } from '@/utils/token';

②获取token

const token = getToken();

③设置无需登录的页面

取name名称,因为404页面的path是一个变化量(path: '/:pathMatch(.*)*',),不能确定

//设置一个不需要进行登录的页面数组
const NoLogin = [ 'login','not-found','test']

2、token不存在情况

①无需登录的页面

无需登录的页面,是可以不需要token的,那么就可以直接放行

//在NoLogin数组中,表示不需要登录,就直接放行
if (NoLogin.includes(to.name)) {
  next()
}

②需要登录的页面

需要登录的页面,但没有token表示登录状态可能过期等情况,需要重新条会登录页面进行登录

//如果不在NoLogin数组中,就表示需要登录,没有token就跳转到登录页面
else{
  next({ name: 'login' })
}

3、token存在情况

①在登录login页面

需要进行,在登录页面,且存在token,表示可以直接跳转到主页面

//如果在登录页面,就跳转到首页
if(to.name == 'login'){
  next({ name: 'main' })
}

②在其他页面

需要通过pinia获取用户信息

Ⅰ简单介绍

Pinia 是 Vue.js 的官方推荐状态管理库。使用 Pinia 的主要目的是为了更简单、更灵活地管理应用程序的状态

Ⅱ参考pinia

 pinia参考:定义一个 Store | Pinia

初始创建vue项目的时候,选择pinia的会有相关数据,如果没有选择pinia可进入官网参考进行安装

安装参考:vue3:pinia安装-CSDN博客

Ⅲ使用pinia获取用户状态信息
建立user.js

在src/stores建立user.js的项目,如果是初始vue项目的话,会自动生成counter.js如下

修改代码

复制counter.js的代码到src/stores/user.js,没有就码字

先清除不要的代码

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', () => {


  return { count, doubleCount, increment }
})

修改名称

根据之前给的例子,可以进行用户信息的获取,设值

路由引用

在路由中的相关位置使用pinia进行数据获取/设置

路径:src/router/index.js

引入方法

import { userStore } from '@/stores/user'

获取用户信息,如果存在账号信息,就放行(有token,有账号信息,可放行)

//读取用户信息
const userstore = userStore();
if (userstore.username) {
  //放行
  next();
}

没有用户信息,但存在token,需要对用户信息进行查询

  • 成功获取用户信息:需要更新store的用户信息,并且更新新的token 
  • 没获取用户信息:删除token,并回到登录页面,需重新登录

apifox建立查询用户信息的接口

新建接口

注意:使用的是get

新建期望

返回用户的基本信息

api封装

 在src/api/user.js中写入获取用户信息的get方法

接口方法引入

 

逻辑端执行没有用户信息,存在token功能

else {
  //如果token存在,用户信息没查询到就去请求用户信息
  var res = await getuserinfo();
  //请求之后,如果请求成功,就设置token,设置用户信息,放行,如果请求失败,就删除token,跳转到登录页面
  if(res.code == 1){
    //设置token和用户信息
    setToken(res.token);
    //将用户信息设置到store中
    userstore.setUserinfo(res.data)
    //放行
    next();
  }
  else{
    //删除token
    delToken();
    //跳转到登录页面
    next({ name: 'login' })
  }
}

 注意:

defineStore的第一个参数是唯一id,如果定义别的store,此参数不能重复

 4、测试效果

①测试token不存在,看是否跳转到登录页面

首先在主页页面,可以查看到基本token信息

右击删除token

再刷新此页面 ,成功跳回login页面

 ②测试token存在,再登录页面是否会直接进入主页面

在主页面,存在token信息

将路径改为login

页面再次回到主页面

四、完整代码

1、pinia获取/设置用户信息

src/stores/user.js


import { computed, reactive } from 'vue'
import { defineStore } from 'pinia'

export const userStore = defineStore('userinfo', () => {
  //声明用户信息
  const userinfo = reactive({});//对象
  //获取用户名等。由于用户名是通过用户信息获取的,所以需要一个计算属性
  const username = computed(() => userinfo.name);
  //设值用户信息
  const setUserinfo = (info) => {
    //对象使用assign,如果userInfo中有相同的key,则info覆盖userInfo的key信息,把之前有的信息进行更换)
    Object.assign(userinfo, info)
  }
  return { userinfo, username ,setUserinfo}
})

2、获取用户信息

src/api/user.js

import { post , get } from '@/utils/request';

// 登录
export function login(data) {
    return post('/user/login', data); 
}
//重置密码-通过手机号
export function repwd(data) {
    return post('/user/repassword', data); 
}
//获取用户信息
export function getuserinfo() {
    return get('/user/getuserinfo'); 
}

3、路由信息

src/router/index.js

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import { getToken, setToken, delToken } from '@/utils/token';
import { userStore } from '@/stores/user'
import { getuserinfo } from '@/api/user';
// 引入路由
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [//将子项全部存入一个大的路由中layout/index.vue,页面刚进入时调用的时layout/index.vue,在为导航条,默认显示页面/home的内容
    {
      path: '/',
      name: 'main',
      component: () => import('@/layout/index.vue'),
      redirect: '/home',
      children: [
        {
          path: '/home',
          name: 'home',
          component: HomeView
        },
        {
          path: '/about',
          name: 'about',
          component: () => import('../views/AboutView.vue')
        },
      ]
    },
    //登录
    {
      path: '/login',
      name: 'login',
      component: () => import('@/views/LoginView.vue'),
      meta: {
        title: '登录'
      }
    },
    //测试页面
    {
      path: '/test',
      name: 'test',
      component: () => import('@/views/TestView.vue'),
      meta: {
        title: '测试页面'
      }
    },
    //404
    {
      path: '/:pathMatch(.*)*',
      name: 'not-found',
      component: () => import('@/views/NotFoundView.vue'),
      meta: {
        title: '页面未找到'
      }
    },

  ],
})

//设置系统标题
const SystemTitle = 'SMS后台管理系统';
//设置一个不需要进行登录的页面数组
const NoLogin = ['login', 'not-found', 'test']
//设置路由守卫
router.beforeEach(async(to, from, next) => {
  if (to.meta.title) {
    //拼接新标题
    var newtitle = to.meta.title + '-' + SystemTitle
    document.title = newtitle
  }
  // 判断是否登录
  const token = getToken();
  //如果token不存在
  if (!token) {
    //在NoLogin数组中,表示不需要登录,就直接放行
    if (NoLogin.includes(to.name)) {
      next()
    }
    //如果不在NoLogin数组中,就表示需要登录,没有token就跳转到登录页面
    else {
      next({ name: 'login' })
    }
  }
  //token存在
  else {
    //如果在登录页面,就跳转到首页
    if (to.name == 'login') {
      next({ name: 'main' })
    }
    else {
      //读取用户信息
      const userstore = userStore();
      console.log(userstore)
      if (userstore.username) {
        //放行
        next();
      }
      else {
        //如果token存在,用户信息没查询到就去请求用户信息
        var res = await getuserinfo();
        console.log(res);
        //请求之后,如果请求成功,就设置token,设置用户信息,放行,如果请求失败,就删除token,跳转到登录页面
        if(res.code == 1){
          //设置token和用户信息
          setToken(res.data.token);
          //将用户信息设置到store中
          userstore.setUserinfo(res.data)
          //放行
          next();
        }
        else{
          //删除token
          delToken();
          //跳转到登录页面
          next({ name: 'login' })
        }
      }
    }
  }
})

export default router

相关文章:

  • Hive Presto SQL 查询优化指南
  • 飞腾2000+/64核加固服务器
  • 【c++】c++语言中““符号的用途介绍
  • 【零基础入门unity游戏开发 —— 通用篇】层级(Layer)、层级编号、层级二进制掩码和unity层级检测原理
  • 【蓝桥杯速成】| 6.背包问题(01版)
  • Nuxt2 vue 给特定的页面 body 设置 background 不影响其他页面
  • 知识管理流程指南
  • Python----计算机视觉处理(Opencv:形态学变换)
  • Bellman_ford 算法--带负权值的单源最短路问题,边列表存储
  • 相机标定之DLT算法学习
  • [HelloCTF]PHPinclude-labs超详细WP-Level 6Level 7Level 8Level 9-php://协议
  • Java高级编程深度解析:JVM底层原理、设计模式与Java 8+新特性实战
  • 案例驱动的 IT 团队管理:创新与突破之路:第三章 项目攻坚:从流程优化到敏捷破局-3.2.1案例:传统企业敏捷转型的“阵痛期“应对
  • 【QT:网络编程】
  • 【大模型理论篇】R1-Searcher:通过强化学习激励llm的搜索能⼒
  • Linux rpm软件管理
  • HTML5扫雷游戏开发实战
  • 计算机视觉算法实战——实例分割(主页有源码)
  • React19源码系列之Hooks(useId)
  • 【设计模式】3W 学习法全面解析 7 大结构型模式:Java 实战 + 开源框架应用
  • 昆明一学校门外小吃摊占满人行道,城管:会在重点时段加强巡查处置
  • 本周看啥|喜欢二次元的观众,去电影院吧
  • 公安部部署“昆仑2025”专项工作,严打环食药等领域突出犯罪
  • 巴基斯坦称约50名印度士兵在克什米尔实控线丧生
  • 法治日报:商品明细是隐私,外卖员快递员不应知晓
  • 中科院院士魏辅文已卸任江西农业大学校长