第二十七节:进阶:路由权限控制 + 404 / 401 全局异常页面开发

发布时间:2026/9/6 2:19:57
第二十七节:进阶:路由权限控制 + 404 / 401 全局异常页面开发 第二十七节进阶路由权限控制 404 / 401 全局异常页面开发本节目标开发 404 页面页面不存在、401 无权限页面完善路由守卫实现路由权限校验区分登录校验、角色 / 权限校验、不存在页面跳转逻辑处理白名单路由登录页不用登录也能访问模拟无权限访问页面跳转 401访问不存在路由跳转 404前面v‑perm控制按钮显示隐藏路由权限控制整个页面能不能进。步骤 1新建两个异常页面① src/views/error/404.vuetemplate div classerror-page div classcode404/div div classdesc抱歉你访问的页面不存在/div el-button typeprimary click$router.push(/dashboard)返回工作台/el-button /div /template script setup/script style scoped .error-page{ height: 100%; display:flex; flex-direction:column; align-items:center; justify-content:center; } .code{ font-size:80px; font-weight:bold; color:#909399; } .desc{ font-size:16px; color:#666; margin:16px 0 24px; } /style② src/views/error/401.vuetemplate div classerror-page div classcode401/div div classdesc抱歉你没有权限访问该页面/div el-button typeprimary click$router.push(/dashboard)返回工作台/el-button /div /template script setup/script style scoped .error-page{ height: 100%; display:flex; flex-direction:column; align-items:center; justify-content:center; } .code{ font-size:80px; font-weight:bold; color:#E6A23C; } .desc{ font-size:16px; color:#666; margin:16px 0 24px; } /style步骤 2配置路由 src/router/index.jsimport { createRouter, createWebHistory } from vue-router import Layout from /layout/index.vue // 常量路由所有用户都可以访问不需要权限 export const constantRoutes [ { path: /login, component: () import(/views/login/index.vue), meta: { title: 登录 } }, { path: /, component: Layout, redirect: /dashboard, children: [ { path: /dashboard, component: () import(/views/dashboard/index.vue), meta: { title: 工作台, icon: DataBoard } } ] }, // 无权限页面 { path: /401, component: () import(/views/error/401.vue) }, // 404页面必须放在路由数组最后 { path: /:pathMatch(.*)*, component: () import(/views/error/404.vue) } ] // 需要权限的业务路由后续动态追加 export const asyncRoutes [ { path: /system, component: Layout, meta: { title: 系统管理, icon: Setting }, children: [ { path: user, component: () import(/views/system/user/index.vue), meta: { title: 用户管理, icon: User } } ] } ] const router createRouter({ history: createWebHistory(), routes: constantRoutes }) export default router步骤 3编写路由守卫 src/permission.js新建src/permission.js全局路由拦截逻辑import router from /router import { useUserStore } from /stores/user // 白名单不需要登录就可以访问的页面 const whiteList [/login,/401,/404] router.beforeEach(async(to, from, next) { const userStore useUserStore() const token userStore.token // 1、有token已经登录 if(token){ if(to.path /login){ // 已经登录访问登录页直接跳工作台 next(/dashboard) }else{ // 判断是否已经获取用户信息 if(!userStore.username){ try { // 这里可以调用接口获取用户信息存入pinia // await getUserInfoApi() // 把动态权限路由追加到路由表 // router.addRoute(asyncRoutes) next({ ...to, replace:true }) }catch(err){ // token失效清空状态回到登录 userStore.logout() next(/login) } }else{ // 已拿到用户信息放行 next() } } }else{ // 2、没有token未登录 if(whiteList.includes(to.path)){ // 在白名单直接放行 next() }else{ // 不在白名单跳登录页 next(/login) } } })步骤 4在 main.js 引入 permission让守卫生效import { createApp } from vue import App from ./App.vue import /permission // ✅导入路由守卫必须写在createApp之前 import ElementPlus from element-plus import element-plus/dist/index.css import * as ElementPlusIconsVue from element-plus/icons-vue import { perm } from /directive/perm const app createApp(App) for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component) } app.directive(perm, perm) app.use(ElementPlus) app.mount(#app)步骤 5动态路由追加重点根据权限动态挂载路由现在所有路由全部写死真正后台项目登录拿到用户权限再调用router.addRoute把有权限的路由注册进去。修改src/permission.js演示动态路由逻辑import router from /router import { useUserStore } from /stores/user import { asyncRoutes } from /router const whiteList [/login,/401,/404] // 模拟过滤路由根据用户权限过滤出可以访问的路由 function filterAsyncRoutes(routes, permissions){ const res [] routes.forEach(route { const temp { ...route } // 简单演示如果是admin直接全部放行 res.push(temp) }) return res } router.beforeEach(async(to, from, next) { const userStore useUserStore() const token userStore.token if(token){ if(to.path /login){ next(/dashboard) }else{ if(!userStore.username){ try { // 模拟登录后获取用户信息这里是mock已经存好 // 根据权限过滤动态路由 const accessRoutes filterAsyncRoutes(asyncRoutes, userStore.permissions) // 将过滤后的路由添加进路由实例 accessRoutes.forEach(item{ router.addRoute(item) }) // addRoute之后必须带上replace:true防止路由404 next({ ...to, replace:true }) }catch(err){ userStore.logout() next(/login) } }else{ next() } } }else{ if(whiteList.includes(to.path)){ next() }else{ next(/login) } } })✅测试验证清单未登录状态直接访问/dashboard、/system/user自动跳转到登录页面访问不存在地址例如http://localhost:5173/xxxabc跳转到 404 页面访问 /401正常渲染无权限页面登录成功动态路由/system/user被 addRoute 注册侧边栏自动渲染系统管理菜单已经登录后手动访问/login自动跳转到工作台关键知识点/:pathMatch(.*)*404 路由必须放在路由数组最后如果写在前面所有页面都会命中 404。router.addRoute()添加动态路由之后next({...to,replace:true})必不可少否则新增路由会报 404。白名单路由不需要 token 也能进入。前端路由权限只是拦截跳转接口层面依旧需要后端做权限校验。踩坑点/permission需要在 main.js 尽早导入要在createApp(App)之前引入守卫才生效。刷新页面 pinia 状态丢失搭配 pinia 持久化插件token、用户信息刷新页面不丢失。