Vue3 + Pinia 实现企业级 RBAC 权限控制系统(学生实战笔记)
大家好我是一名正在学习前端开发的大二学生。最近在做Vue3 能源管理平台项目时遇到了权限控制这个核心难点。为了真正理解并掌握它我把实现过程、踩过的坑、完整代码都整理成这篇笔记既方便自己回顾也分享给同样在学习的同学在企业后台管理系统里RBAC 基于角色的权限控制是必考点也是真实项目里最常用的方案。这篇文章完全按照学生学习视角从思路到代码一步步写不搞复杂术语能直接看懂、直接用在自己的项目里。项目完整源码我已放到 GitHubhttps://github.com/HY-koi/Vue3-Energy-Management-Platform欢迎大家 Star、Fork一起学习交流一、为什么要做权限控制在做后台管理项目时我们经常需要不同角色看到不同菜单未登录不能进页面某些按钮只有管理员能看见刷新页面不能白屏、不能丢失权限这些需求靠简单的判断根本不够用必须用一套完整的 RBAC 权限方案。二、我的实现思路学生易懂版用户登录拿到 token根据 token 请求用户信息与菜单列表把后端返回的菜单转成前端路由用router.addRoute动态挂载路由用 Pinia 保存权限、菜单、用户信息路由守卫做登录判断与权限恢复自定义指令实现按钮级权限三、完整实现代码可直接复制到项目1. 路由基础配置typescript运行// src/router/index.ts import { createRouter, createWebHistory } from vue-router const routes [ { path: /login, component: () import(/views/login/index.vue) }, { path: /:pathMatch(.*)*, component: () import(/views/404.vue) } ] const router createRouter({ history: createWebHistory(), routes }) export default router2. Pinia 权限仓库核心typescript运行// src/store/auth.ts import { defineStore } from pinia import { ref } from vue import router from /router export const useAuthStore defineStore(auth, () { const token ref() const userInfo ref(null) const menuList ref([]) const permissions ref([]) // 保存 token const setToken (val) { token.value val localStorage.setItem(token, val) } // 动态添加路由 const addRoutes (menus) { menus.forEach((item) { if (item.path item.component) { router.addRoute({ path: item.path, name: item.name, component: () import(/views/${item.component}), meta: { title: item.title, icon: item.icon } }) } if (item.children) { item.children.forEach((child) { router.addRoute(item.name, { path: child.path, name: child.name, component: () import(/views/${child.component}), meta: { title: child.title } }) }) } }) } return { token, userInfo, menuList, permissions, setToken, addRoutes } })3. 路由守卫解决刷新丢失typescript运行// src/router/guard.ts import router from ./index import { useAuthStore } from /store/auth import { getUserInfo } from /api/user router.beforeEach(async (to, from, next) { const store useAuthStore() const token store.token || localStorage.getItem(token) // 未登录 if (!token) { return to.path /login ? next() : next(/login) } // 刷新后重新获取权限 if (store.menuList.length 0) { const { data } await getUserInfo() store.menuList data.menuList store.permissions data.permissions store.addRoutes(data.menuList) return next({ ...to, replace: true }) } next() })4. 按钮权限指令 v-permissiontypescript运行// src/directives/permission.ts import { useAuthStore } from /store/auth export default { mounted(el, binding) { const store useAuthStore() if (!store.permissions.includes(binding.value)) { el.style.display none } } }typescript运行// main.ts 全局注册 import permission from /directives/permission app.directive(permission, permission)使用html预览el-button v-permissionstation:add新增充电站/el-button四、我踩过的坑给同学避坑刷新页面路由丢失解决在路由守卫里判断菜单是否为空为空就重新获取。404 页面把正常路由挡住解决404 路由放在最后。Vite 不能用变量直接 import解决使用字符串映射或提前配置组件路径。按钮权限不生效解决检查权限标识是否完全一致。五、学习总结学生视角通过这次实战我真正掌握了什么是 RBAC 权限系统动态路由如何实现路由守卫的实际使用Pinia 状态管理自定义指令的应用企业项目的常见问题处理这套代码我已经用在自己的Vue3 能源管理平台中运行稳定逻辑清晰非常适合学生用来学习、做课程设计、写简历项目。项目源码https://github.com/HY-koi/Vue3-Energy-Management-Platform如果你也在做后台管理系统希望这篇笔记能帮到你