目录
2、在全局路由守卫中设置跳转规则(未登录则跳转到登录页,已登录跳转到首页或放行)
3、在登录页中登录获取路由和用户信息后pinia存储用户信息并动态添加路由
5、防止浏览器刷新后出现404(因为刷新后相当于项目重新运行,添加的动态路由就没了)
一、基本用法
注:这里只说编程式路由导航,(不说<router-link>,项目中基本不用,也没法写逻辑)
基础知识:useRoute 和 useRouter 的区别
useRoute:
用于在组件中获取当前路由的信息,返回一个包含路由信息的对象。这个函数适用于那些不需要监听路由变化的场景,只是获取当前路由信息的静态数据。
useRouter:
用于获取路由实例,可以通过它来进行一些动态的路由操作,比如跳转到新的路由。它返回一个包含路由实例的对象。其中包括当前路由
信息。
1、字符串写法
push
是追加历史记录,replace
是替换当前记录
import { useRouter } from 'vue-router' const router = useRouter() const toHome = () => { router.push('/home') } const toAbout = () => { router.replace('/about') }
2、对象写法
注意:query传参对象里面可以写name或者path,params传参对象里面匹配只能写name
// query传参 import { useRouter } from 'vue-router' const router = useRouter() const toHome = () => { router.push({ path: '/home' query: { id: 1, title: '震惊,老婆饼里没老婆' } }) } // 接收 import { useRoute } from 'vue-router' const route = useRoute() console.log(route.query)
// params传参 import { useRouter } from 'vue-router' const router = useRouter() const toAbout = () => { router.replace({ name: 'about', params: { id: 1, title: '震惊,老婆饼里没老婆' } }) } // 接收 import { useRoute } from 'vue-router' const route = useRoute() console.log(route.params) // params传参需要路由表配合使用 ?代表可传可不传 { path: '/about/:id/:title?', name: 'about', component: () => import('../views/AboutView.vue') }
二、路由守卫
分类:全局守卫、单个路由守卫、组件内部守卫
1、全局守卫
beforeEach()
全局前置守卫:初始化时执行、每次路由切换前执行;
三个参数:
to:要跳转到的目标路由
from:从当前哪个路由进行跳转
next:不做任何阻拦,直接通行,该往哪个路由跳转就往哪个跳转
route中有一个配置项是meta,专门提供给我们,在meta项中配置自己的属性与值,可用于在守卫中的权限判断
//前置路由 import { userStore } from '../store/userInfo'; router.beforeEach((to, from, next) => { const store = userStore(); //判断是否有权限返回登录界面 if (from.meta.isAuth) { if (store.userInfo.token) { next() } else { next("/login") } } else { console.log("没有权限"); next() } })
全局后置路由守卫afterEach
对于分析、更改页面标题、声明页面等辅助功能都很有用
//后置路由 router.afterEach((to, from) => { console.log("全局后置路由守卫"); //设置跳转路由后页面的标题 document.title = to.meta.title as string })
2、独享守卫beforeEnter
直接在需要设置权限的路由配置中写代码,代码逻辑和全局前置路由一模一样
..... , { name: 'order', path: 'order', meta: { isAuth: true, title: '订单管理' }, component: () => import("../components/page/Order.vue"), //独享守卫 beforeEnter: (to: any, from: any, next: any) => { console.log("路由独享守卫beforeEnter"); next() } }
三、动态路由
1、配置静态路由
const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: '/login', name: 'login', component: LoginView } ] })
2、在全局路由守卫中设置跳转规则(未登录则跳转到登录页,已登录跳转到首页或放行)
import { useUserInfoStore } from '@/stores/userInfo' router.beforeEach((to: any, from: any, next: any) => { // 从pinia获取用户的登录状态 const userInfo = useUserInfoStore() // 注意:这个取值只能写在函数里,不然报错,因为写在外面app.use(router)的时候就调用了,当时还没有加载到pinia if (userInfo.isLogin) { if (to.path === '/login') { next({ path: '/home' }) } else { next() } } else { if (to.path === '/login') { next() } else { next({ path: '/login' }) } } })
3、在登录页中登录获取路由和用户信息后pinia存储用户信息并动态添加路由
pinia使用及持久化存储请访问:pinia使用方法-CSDN博客
//简单写的pinia存储登录状态 import { ref } from 'vue' import { defineStore } from 'pinia' export const useUserInfoStore = defineStore( 'userInfo', () => { const isLogin = ref(false) function changeIsLogin(state: boolean) { isLogin.value = state } return { isLogin, changeIsLogin } }, { persist: true } )
import { useRouter } from 'vue-router' import { useUserInfoStore } from '@/stores/userInfo' const userInfo = useUserInfoStore() const router = useRouter() const login = () => { userInfo.changeIsLogin(true) // 这里是要追加的动态路由,这里随便写死的,按理说正常开发应该从后端返回,然后前端拿到后转成这样的数组存在pinia const routerArr = [ { path: '/', redirect: '/home' }, { path: '/home', name: 'home', component: HomeView }, { path: '/:pathMatch(.*)', //必须写 (/:pathMatch(.*)* 可以匹配任意路径,包括根路径和子路径。) name: '404', component: NotFount }, { path: '/about/:id?/:title?', name: 'about', component: () => import('../views/AboutView.vue') } ] routerArr.forEach((item) => { router.addRoute(item) }) router.replace('/home') }
4、退出登录后移除动态路由
const quit = () => { userInfo.changeIsLogin(false) // 这里是退出登录后要删除的路由,这里随便写死的,按理说正常开发应该从后端返回,然后前端拿到后转成这样的数组存在pinia const routerArr = ['home', '404', 'about'] routerArr.forEach((item) => { router.removeRoute(item) }) router.replace('/login') }
5、防止浏览器刷新后出现404(因为刷新后相当于项目重新运行,添加的动态路由就没了)
这里做法是使用isReady方法,它返回一个 Promise,它会在路由器完成初始导航之后被解析,也就是说这时所有和初始路由有关联的异步入口钩子和异步组件都已经被解析。如果初始导航已经发生,则该 Promise 会被立刻解析。
当刷新页面后路由器初始化完成后如果用户已登录重新追加动态路由
router.isReady().then(() => { const userInfo = useUserInfoStore() if (userInfo.isLogin) { // 这里是要追加的动态路由,这里随便写死的,按理说正常开发应该从后端返回,然后前端拿到后转成这样的数组存在pinia const routerArr = [ { path: '/', redirect: '/home' }, { path: '/home', name: 'home', component: HomeView }, { path: '/:pathMatch(.*)', //必须写 (/:pathMatch(.*)* 可以匹配任意路径,包括根路径和子路径。) name: '404', component: NotFount }, { path: '/about/:id?/:title?', name: 'about', component: () => import('../views/AboutView.vue') } ] routerArr.forEach((item) => { router.addRoute(item) }) router.replace(router.currentRoute.value.fullPath) } })