0


前端单独实现 vue 动态路由

前端单独实现 vue 动态路由

Vue 动态路由权限是指在 Vue 应用程序中,根据用户的权限动态生成和控制路由的行为。这意味着不是所有的路由都在应用启动时就被硬编码到路由配置中,而是根据用户的权限信息,在运行时动态地决定哪些路由应该被加载和显示。

动态路由的优点:

  • 安全性:- 只有经过验证的用户才能访问其权限范围内的页面。- 减少了由于硬编码路由导致的安全漏洞。
  • 灵活性:- 可以根据用户的权限动态调整应用的结构,无需重新部署整个应用即可调整路由。- 支持按需加载(懒加载),提高应用性能。
  • 用户体验:- 只展示用户可以访问的菜单项,避免显示无用链接,提高用户体验。- 用户界面更加简洁,只显示与其角色相关的功能。
  • 可维护性:- 简化了路由配置,因为不需要为每个角色单独编写路由配置,而是集中管理权限。- 更容易扩展和修改权限配置,只需更新前端的权限数据即可。
  • 开发效率:- 开发者只需要关注业务逻辑,而不需要关心每个角色的具体路由配置。- 减少了重复工作,提高了开发效率。

实现步骤

  • 定义静态路由配置:- 在项目中定义一个包含所有可能路由的静态配置文件或对象,每个路由可以附加权限信息(如角色、访问级别等)。
  • 用户登录与鉴权:- 用户登录时,前端存储用户的权限信息(如角色、权限列表等)。
  • 动态生成路由:- 根据用户的权限信息,从前端的静态路由配置中筛选出用户有权访问的路由。- 使用递归算法或其他逻辑动态生成路由配置,并添加到 Vue Router 实例中。
  • 动态渲染菜单:- 根据动态生成的路由表来渲染左侧菜单或顶部导航栏,确保只显示用户有权访问的菜单项。

代码示例

配置路由器

router/index.js

// router/index.jsimport Vue from'vue'import VueRouter from'vue-router'import Layout from'@/Layout/index.vue'

Vue.use(VueRouter)// export const roleMap = {//     '-1':'运维管理员',//     '1':'普通用户',//     '2':'项目经理',//     '3':'部门管理员',//     '4':'综合部管理员',//     '5':'部门领导'// }// 公共路由exportconst routes =[{path:'/',name:'redirect',component: Layout,hidden:true,// 隐藏菜单redirect:"/homePage",// 用户在地址栏输入 '/' 时会自动重定向到 /homePage 页面},{path:'/homePage',component: Layout,redirect:"/homePage/index",meta:{title:"首页",},children:[{path:'index',name:'homePageIndex',meta:{title:"首页",},component:()=>import('@/views/homePage/index.vue')}]},{path:'/login',component:()=>import('@/views/login.vue'),hidden:true},{path:'/404',component:()=>import('@/views/error/404.vue'),hidden:true},{path:'/401',component:()=>import('@/views/error/401.vue'),hidden:true},]// 动态权限路由exportconst dynamicRoutes =[{path:'/admin',meta:{title:"系统管理",},component: Layout,permission:['-1','2','3','4','5'],// all 所有角色都可以访问  1 普通用户  2 项目经理  3 部门管理员  4 综合部管理员  5  部门领导  -1 项目运维管理员children:[{path:'user',name:'userIndex',meta:{title:"用户管理",},permission:['-1','2','3','4','5'],component:()=>import('@/views/admin/user/index.vue')},{path:'role',name:'roleIndex',meta:{title:"角色管理",},permission:['-1','2','3','4','5'],component:()=>import('@/views/admin/role/index.vue'),children:[{path:'add',name:'addRole',meta:{title:"添加角色",},permission:['-1',,'3','4','5'],component:()=>import('@/views/admin/user/index.vue')},{path:'update',name:'updateRole',meta:{title:"编辑角色",},permission:['-1','2','3','4','5'],component:()=>import('@/views/admin/role/index.vue')}]}]},{path:'/tableEcho',meta:{title:"表格管理",},component: Layout,permission:['-1','1','2'],children:[{path:'test',name:'tableEchoIndex',meta:{title:"表格测试",},permission:['-1','1','2'],component:()=>import('@/views/tableEcho/index.vue'),children:[{path:'add',name:'addTable',hidden:true,meta:{title:"新增测试",},permission:['-1','2'],component:()=>import('@/views/tableEcho/add.vue')}]},],},]const router =newVueRouter({base: process.env.BASE_URL,
  routes
})exportdefault router

上述代码定义了一个公共路由

routes

和一个动态权限控制的路由

dynamicRoutes 

,

permission

数组定义了哪些角色拥有该路由权限, 将用户分为6个角色级别, 每个角色对应不同的角色级别,分别为

  • ‘-1’:‘运维管理员’,
  • ‘1’:‘普通用户’,
  • ‘2’:‘项目经理’,
  • ‘3’:‘部门管理员’,
  • ‘4’:‘综合部管理员’,
  • ‘5’:‘部门领导’,

封装路由守卫

permission.js

// permission.jsimport router from'./router'import store from'./store'import{ Message }from'element-ui'import{ getStore }from'@/utils/store';const whiteList =['/login','/404','/401'];

router.beforeEach((to, from, next)=>{let token =getStore('token');if(token){/* has token*/if(to.path ==='/login'){next({path:'/'});}else{if(store.getters.roles.length ===0){// 判断当前用户是否已拉取完user_info信息
        store.dispatch('GetInfo').then((res)=>{
          console.log('--------------', res);
          router.addRoutes(res)// 动态添加可访问路由表next({...to,replace:true})// hack方法 确保addRoutes已完成}).catch(err=>{
          store.dispatch('LogOut').then(()=>{
            Message.error(err)next(`/`)})})}else{next()}}}else{// 没有tokenif(whiteList.indexOf(to.path)!==-1){// 在免登录白名单,直接进入next()}else{next(`/login`)// 否则全部重定向到登录页}}})

上述代码表示在路由的

beforeEach

函数里面调用 vuex 里面

actions

里的方法发送接口请求获取用户信息与用户角色权限, 最后通过

router.addRoutes(res)

渲染路由
permission.js 文件需引入到 main.js里面

如果项目

vue-router

版本超过 3.3.0, 需要遍历路由数组再使用

router.addRoute()

方法逐个添加路由

res.forEach(route=>{
    router.addRoute(route);})

在 vuex 里获取用户所拥有的权限, 过滤该权限不拥有的路由

store/index.js

// store/index.jsimport Vue from'vue'import Vuex from'vuex'import{ routes, dynamicRoutes }from"@/router";import{ login, getInfo, logout }from"@/api/user";import{ setStore, clearStore }from'@/utils/store';

Vue.use(Vuex)exportdefaultnewVuex.Store({state:{
    routes,token:"",roleType:"",roles:[],permissions:[],sidebarRouters:[],},getters:{token:state=> state.token,roles:state=> state.roles,permissions:state=> state.permissions,sidebarRouters:state=> state.sidebarRouters,},mutations:{SET_TOKEN:(state, token)=>{
      state.token = token;},SET_USERINFO:(state, user)=>{
      state.userInfo = user;},SET_ROLETYPE:(state, roleType)=>{
      state.roleType = roleType;},SET_ROLES:(state, roles)=>{
      state.roles = roles;},SET_PERMISSIONS:(state, permissions)=>{
      state.permissions = permissions;},SET_ROUTE:(state, sidebarRouters)=>{
      state.sidebarRouters = sidebarRouters;},},actions:{Login({ commit }, userInfo){returnnewPromise((resolve, reject)=>{login(userInfo).then(res=>{setToken(res.data.token);setStore('token', res.data.token);commit('SET_TOKEN', res.data.token);resolve();}).catch(error=>{reject(error);})})},// 获取用户信息GetInfo({ commit }){returnnewPromise((resolve, reject)=>{getInfo().then(res=>{
          console.log('res::: ', res);if(res.data.code ===0||200){const user = res.data.sysUser;const roleType = res.data.roleType;commit('SET_USERINFO', user);// roleType 用户所用的权限级别 1 普通用户  2 项目经理  3 部门管理员  4 综合部管理员  5  部门领导  -1 项目运维管理员setStore('ROLE_TYPE', roleType);if(res.data.roles){// 验证返回的roles是否为真commit('SET_ROLES', res.data.roles);commit('SET_PERMISSIONS', res.data.permissions);}else{commit('SET_ROLES',['ROLE_DEFAULT']);}// 过滤路由let newRouters =filterRouter(roleType, dynamicRoutes);// 连接公共路由const sidebarRouters = routes.concat([...newRouters])commit('SET_ROUTE', sidebarRouters);resolve(sidebarRouters);}else{reject(error);}}).catch(error=>{reject(error);})})},// 退出系统LogOut({ commit, state }){returnnewPromise((resolve, reject)=>{logout(state.token).then(()=>{commit('SET_TOKEN','')commit('SET_ROLES',[])commit('SET_PERMISSIONS',[])clearStore('token');clearStore('userInfo')resolve()}).catch(error=>{reject(error)})})},},modules:{}})functionfilterRouter(roleType, routes){return routes.filter(item=>{// filter 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素,测试未通过的元素会自动剔除// 如果一级路由的 permission 含有当前角色的 roleTypeif(item.permission.includes(roleType)){// 如果该一级路由含有子路由时,递归调用该函数判断子路由是否有权限if(Array.isArray(item.children)&& item.children.length >0){// 递归调用该函数,最后接受校验通过后的子路由let newChildren =filterRouter(roleType, item.children);// 如果子路由有值,则赋值给当前路由的 children,剔除校验不通过的子路由if(newChildren.length >0){
          item.children = newChildren;}elseif(newChildren.length ===0){// 如果子路由为空,则删除该路由的 children 属性delete item.children;}}// 最后返回 true, 表示该路由通过权限校验returntrue;}})}

上述代码通过

getInfo

接口获取用户权限, 通过函数

filterRouter

过滤掉该角色不拥有的路由, 通过

concat

方法合并

routes

公共路由, 最后通过

resolve

返回

文件布局如下

在这里插入图片描述

下图为页面渲染的菜单(项目经理角色)

在这里插入图片描述

左侧菜单实现参考链接: Elemnt-UI + 递归组件实现后台管理系统左侧菜单

前端结合后端接口请求实现动态路由参考连接: 前端 + 接口请求实现 vue 动态路由

总结

在用户登录成功后从服务器获取用户的权限信息,在 vuex 的异步处理函数中过滤掉角色权限不存在的路由,使用

concat()

合并公共路由,最后使用

router.addRoutes(res)

动态添加可访问的路由。这样可以确保应用根据用户的权限动态加载相应的路由,增强安全性与灵活性。


本文转载自: https://blog.csdn.net/a123456234/article/details/141975858
版权归原作者 你不讲 wood 所有, 如有侵权,请联系我们删除。

“前端单独实现 vue 动态路由”的评论:

还没有评论