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 = s['User/accessToken']
if (!settings.loginInterception) hasToken = true
if (hasToken) {
if (to.path === '/auth/sign-in') {
next({ path: '/' })
} else {
const hasPermissions =
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 (utesWhiteList.indexOf(to.path) !== -1) {
next()
} else {
next('/auth/sign-in')
}
}
document.title = a.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
react router拦截* @description 路由拦截状态管理
*/
import { asyncRoutes, constantRoutes } from '@/router'
import { filterAsyncRoutes } from '@/Utils/handleRoutes'
const state = () => ({
routes: [],
partialRoutes: []
})
const getters = {
routes: (state) => utes,
partialRoutes: (state) => state.partialRoutes
}
const mutations = {
setRoutes (state, routes) {
},
setPartialRoutes (state, routes) {
state.partialRoutes = at(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 (a && a.permissions) {
return permissions.some((role) => a.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: 'auth1',
component: AuthLayout,
children: authChildRoutes('auth1'),
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' : a.is_heading ? 'iq-menu-title' :activeLink(item) && item.children ? 'active' : activeLink(item) ? 'active' : ''">
<template v-if="!item.hidden">
<i v-if="a.is_heading && hideListMenuTitle" class="ri-subtract-line" />
<span v-if="a.is_heading && hideListMenuTitle">{{ $a.name) }}</span>
<router-link :to="a.link" v-if="!item.is_heading" :class="`iq-waves-effect ${activeLink(item) && item.children ? 'active' : activeLink(item) ? 'active' : ''}`" v-b-toggle="a.name">
<i :class="a.icon" v-if="a.is_icon_class"/>
<template v-else v-html="a.icon">
</template>
<span>{{ $a.name) }}</span>
<i v-if="item.children" class="ri-arrow-right-s-line iq-arrow-right" />
<small v-html="a.append" v-if="hideListMenuTitle" :class="a.append_class" />
</router-link>
<List v-if="item.children" :items="item.children" :sidebarGroupTitle="hideListMenuTitle" :open="a.link.name !== '' && activeLink(item) && item.children ? true : !!(a.link.name !== '' && activeLink(item))" :idName="a.name" :accord      </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) {
ActiveLink(item, this.$route.name)
}
}
}
</script>
到此这篇关于vue-router 基于后端permissions动态⽣成导航菜单的⽰例代码的⽂章就介绍到这了,更多相关vue-router permissions导航菜单内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后
多多⽀持!