温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》
  • 首页 > 
  • 教程 > 
  • 开发技术 > 
  • 如何编写vue-router基于后端permissions动态生成导航菜单的代码

如何编写vue-router基于后端permissions动态生成导航菜单的代码

发布时间:2021-09-30 14:49:48 来源:亿速云 阅读:158 作者:iii 栏目:开发技术

本篇内容主要讲解“如何编写vue-router基于后端permissions动态生成导航菜单的代码”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何编写vue-router基于后端permissions动态生成导航菜单的代码”吧!

目录
  • Vue.js

  • 1、注册全局守卫

  • 2、Vuex状态管理 全局缓存routes

  • 3、路由拦截

  • 4、路由菜单

  • 5、递归菜单vue组件

Vue.js

  • vue-router

  • vuex

1、注册全局守卫

核心逻辑
1、token身份验证(后端) => token失效返回登录页面
2、获取用户权限
3、校验permissions,动态添加路由菜单

router.beforeResolve 注册一个全局守卫。和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

router.beforeResolve(async (to, from, next) => {   let hasToken = store.getters['User/accessToken']   if (!settings.loginInterception) hasToken = true   if (hasToken) {     if (to.path === '/auth/sign-in') {       next({ path: '/' })     } else {       const hasPermissions =         store.getters['User/permissions'] &&         store.getters['User/permissions'].length > 0       if (hasPermissions) {         next()       } else {         try {           let permissions           if (!constant.loginInterception) {             // settings.js loginInterception为false时,创建虚拟权限             await store.dispatch('User/setPermissions', ['admin'])             permissions = ['admin']           } else {             permissions = await store.dispatch('User/getUserInfo')           }           let accessRoutes = []           accessRoutes = await store.dispatch('Routes/setRoutes', permissions)           // 添加路由           router.addRoutes(accessRoutes)           next({ ...to, replace: true })         } catch {           await store.dispatch('User/resetAccessToken')         }       }     }   } else {     if (settings.routesWhiteList.indexOf(to.path) !== -1) {       next()     } else {       next('/auth/sign-in')     }   }   document.title = getPageTitle(to.meta.title) })

settings.js 全局设置

export default {   // 是否开启登录拦截   loginInterception: true,   // 不经过token校验的路由   routesWhiteList: ['/auth/sign-in', '/auth/register', '/401', '/404'], }

2、Vuex状态管理 全局缓存routes

  • state :对数据的全局存储

  • getter: 可以理解为computed ,对数据进行计算

  • mutations :对数据的同步更改

  • actions:对数据的异步更改(实现异步操作)

  • module: 将 store 分割成模块

/**  * @author Alan  * @description 路由拦截状态管理  */ import { asyncRoutes, constantRoutes } from '@/router' import { filterAsyncRoutes } from '@/Utils/handleRoutes' const state = () => ({   routes: [],   partialRoutes: [] }) const getters = {   routes: (state) => state.routes,   partialRoutes: (state) => state.partialRoutes } const mutations = {   setRoutes (state, routes) {     state.routes = constantRoutes.concat(routes)   },   setPartialRoutes (state, routes) {     state.partialRoutes = constantRoutes.concat(routes)   } } const actions = {   async setRoutes ({ commit }, permissions) {     const finallyAsyncRoutes = await filterAsyncRoutes(       [...asyncRoutes],       permissions     )     commit('setRoutes', finallyAsyncRoutes)     return finallyAsyncRoutes   },   setPartialRoutes ({ commit }, accessRoutes) {     commit('setPartialRoutes', accessRoutes)     return accessRoutes   } } export default { namespaced: true, state, getters, mutations, actions }

3、路由拦截

/**  * @author Alan  * @description 判断当前路由是否包含权限  * @param permissions  * @param route  * @returns {boolean|*}  */ export function hasPermission (permissions, route) {   if (route.meta && route.meta.permissions) {     return permissions.some((role) => route.meta.permissions.includes(role))   } else {     return true   } } /**  * @author Alan  * @description 根据permissions数组拦截路由  * @param routes  * @param permissions  * @returns {[]}  */ export function filterAsyncRoutes (routes, permissions) {   const finallyRoutes = []   routes.forEach((route) => {     const item = { ...route }     if (hasPermission(permissions, item)) {       if (item.children) {         item.children = filterAsyncRoutes(item.children, permissions)       }       finallyRoutes.push(item)     }   })   return finallyRoutes }

4、路由菜单

/* * @author Alan * @description 公共路由 */ export const constantRoutes = [   {     path: '/auth',     name: 'auth2',     component: AuthLayout,     children: authChildRoutes('auth2'),     hidden: true // 隐藏菜单   },   {     path: '/',     name: 'dashboard',     component: VerticleLayout,     meta: {       title: 'Dashboard',       name: 'sidebar.dashboard',       is_heading: false,       is_active: false,       link: '',       class_name: '',       is_icon_class: true,       icon: 'ri-home-4-line',       permissions: ['admin']     },     children: childRoutes('dashboard')   } ] /* * @author Alan * @description 异步路由 */ export const asyncRoutes = [   {     path: '/menu-design',     name: 'horizontal-dashboard',     component: HorizantalLayout,     meta: {       title: 'Menu Design',       name: 'sidebar.MenuDesign',       is_heading: false,       is_active: false,       link: '',       class_name: '',       is_icon_class: true,       icon: 'ri-menu-3-line',       permissions: ['admin']     },     children: horizontalRoute('dashboard')   }, {     path: '/core',     name: 'core',     component: VerticleLayout,     meta: {       title: 'UI Elements',       name: 'sidebar.uiElements',       is_heading: false,       is_active: false,       class_name: '',       link: '',       is_icon_class: true,       icon: 'ri-pencil-ruler-line',       permissions: ['admin']     },     children: coreChildRoute('core')   } ]

5、递归菜单vue组件

<template>   <b-collapse tag="ul" :class="className" :visible="open" :id="idName" :accordion="accordianName">     <li v-for="(item,index) in items" :key="index" :class=" !hideListMenuTitle? 'p-0' : item.meta.is_heading ? 'iq-menu-title' :activeLink(item) && item.children ? 'active' : activeLink(item) ? 'active' : ''">       <template v-if="!item.hidden">         <i v-if="item.meta.is_heading && hideListMenuTitle" class="ri-subtract-line" />         <span v-if="item.meta.is_heading && hideListMenuTitle">{{ $t(item.meta.name) }}</span>         <router-link :to="item.meta.link" v-if="!item.is_heading" :class="`iq-waves-effect ${activeLink(item) && item.children ? 'active' : activeLink(item) ? 'active' : ''}`" v-b-toggle="item.meta.name">           <i :class="item.meta.icon" v-if="item.meta.is_icon_class"/>           <template v-else v-html="item.meta.icon">           </template>           <span>{{ $t(item.meta.name) }}</span>           <i v-if="item.children" class="ri-arrow-right-s-line iq-arrow-right" />           <small v-html="item.meta.append" v-if="hideListMenuTitle" :class="item.meta.append_class" />         </router-link>         <List v-if="item.children" :items="item.children" :sidebarGroupTitle="hideListMenuTitle" :open="item.meta.link.name !== '' && activeLink(item) && item.children ? true : !!(item.meta.link.name !== '' && activeLink(item))" :idName="item.meta.name" :accordianName="`sidebar-accordion-${item.meta.class_name}`" :className="`iq-submenu ${item.meta.class_name}`" />       </template>     </li>   </b-collapse> </template> <script> import List from './CollapseMenu' // 自身组件 import { core } from '../../../config/pluginInit' export default {   name: 'List',   props: {     items: Array,     className: { type: String, default: 'iq-menu' },     open: { type: Boolean, default: false },     idName: { type: String, default: 'sidebar' },     accordianName: { type: String, default: 'sidebar' },     sidebarGroupTitle: { type: Boolean, default: true }   },   components: {     List   },   computed: {     hideListMenuTitle () {       return this.sidebarGroupTitle     }   },   mounted () {   },   methods: {     activeLink (item) {       return core.getActiveLink(item, this.$route.name)     }   } } </script>

到此,相信大家对“如何编写vue-router基于后端permissions动态生成导航菜单的代码”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI