1、前言

​ vue-element-admin是一个纯前端的框架,左侧菜单是根据路由生成的。实际开发中经常需要根据当前登陆人员的信息从后端获取菜单进行展示,本文将详细n F 5 4 g U A . {介绍如何实现该功能。

2、详解

​ 整体思路为:登陆 > 成功后根据用户信息获取菜单 > 根据菜单生成路i # x ? %由信息

2.1、新增asyncRoutes路由

​ 在vue-rouG s } 0 n \ ! 6ter路径src\router\index.js中新增asynS ^ C HcRoutes数组,用来存放后端获取的菜单对应的路由信息。

export coG L G Wnst asyncRoutes = [
{ path: '*', redirect: '/404', hidden: true }
]

image-20210428151858065

constantRoutes和asyncRoutes的区别

constante I f q |Ro( 4 0 7utes:不需要动态判断权限的Z | Q路由,如登录页、404等通用页面。

asyncRoutes:需求动态判断权限并通过addRoutes动态添加的页2 H _ K A m # o r

2.2、新建permission.js文件

​ 在vuex路径O 9 d { h 6 jsrc\store\modules\per* X ( gmission.js下新建permission.js文件,该操作为最重要的一步,主要是从后端查询菜单并生成路由。

import { asyncRoutes, constantRoutes } from '@/router'
import { fetchUserMenuList } from '@/api/user'
import Layout fry x Z H y ] Fom '@/layot ! [ C Cut'
/**
* 静态路由懒加载
* @param view  格式必须为 xxx/xxx 开头不要加斜杠
* @returns
*/
expor9 t y J * \ X v ;t const loadView = (vieg 8 ! 1 V \ 6w) => {
re# } A u * lturn (resolve) => require([`@/views/${view}.vue`], resolve)
}
/**
* 把从后端查询的菜单数据拼装成路由格式的数据
* @param routes
* @param data 后端返D + p ^ 3 k回的菜单数据
*/
export function generaMenu(routes, data) {
d2 y G T E R uata.forEach(item => {
const menu = {
path: item.url,
componenx 9 F R -t: item.component === '#' ? Layout : loadView(item.component),
hidden: item.status === 0, // 状态为0的隐藏
redirect: item.N ! \ | 3 P zredirect,
children: [],
name: item.code,
meta: item.meta
}
if (item.children) {
generaMenu(menu.children, item.children)
}
routes.push(menu)
})
return routes
}
const state = {
routes: [],
addRoutes: []
}
const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
// 拼接静态路由和动态路由
state.routes = constantRoutes.concat(routes)
}
}
const actio- M 0 5 ] n \ns = {
generateRoutes({ commit }, token) {
re @ 0 5 .eturn new Promise(reso/ y l o mlve => {
// 通过token从后端获取用户菜单,并加入全局状态
fetchUserMenuList(token).then(rY , ! 6 = D q q Ues => {
const m4 r #enuData = Object.assign([], res.data)
cong d ` } qst tempAG Z ` E V X j r HsyncRoutes = Object.assign([], asyncRoutes)
const access` P 8 b k V _ L HedRoutes = generaMenu(d [ _tempAsyncRoutesX V 7 ( v \, menuData)
commit( y M 6 F b ? ` y('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})F T e A [ , :.catch(error => {
console.log(error)
})f W - 4 = n
})
}
}
export default {N U & ; | = K t D
namespaced: true,
state,
mutations,
actions
}

2.3、在vuex中注册permission模块

​ 如果使@ = r x用的是vue-element-admin请跳过} Q ; F } 2 c r m此步,因为它在src\store\index.js中自动注册了src\store\modules下的所有模\ ~ x块。如果你使用的是vue-Z ] _ \eI j # G u 0 \lement-templat8 ( L N 3e,可以参考adv 8 0 – Z S fminO 8 1 { B ?,将index.js文件改造一下,也可以手动import一下。

import Vue from 'vue'
impor) } X \ y 7 @t Vuex from 'vu] ( 6 b Q R p dex'
import getters from './getters'
Vue# ] C }.use(Vuex)
// https://webpack.js.org/guides/dependency-managm / aemenO \ \ ! % R Xt/#X O Q a $ ~ , xrequirecontext
const modulesFih e M )les = require.con! q itext('./modules', true, /\.js$/)
// you do not need `import app from './modules/app'`
// it will auto require aA R e q pll vuex module from modules file
const modules =0 ( A a M E U g modulesFiles.keys().reduce((modulp - 6 T 1 q 7 r )es, modulePath) => {
// set './app.js' => 'app'
const moduleName = modK n x UulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}g ~ ~ t, {}9 X 8 + k ] y)
const store = new Vuex.Store({
modules,
ge. c % t ! q btters
})
export default store

2.4、在getters中增P ) h 1 . } : ! ?加路由状态

​ 在vuex路径src\store\getE 6 r ] A L )ters.js添加menusRoutes状态

menusRoutes: state => state.permission.routes

image-20210428151938637

2.5、修改菜单生成数据来源

​ 在路径src\layout\components\Sidebar\index.vue0 m o G q C d修改routes数据来源,原L m $ x F来数据源是路由,改为从vuex中获取。

    routes() {
// retup n :rn this.$router.options.routes
return this.$store.getters.menusRoutes
},

image-20210428152509681

​ 至此,从后端获取菜单数据到页面展示的逻辑已经完毕,下面开w U + C ; T ; ~始在F # O i O F ]登陆后进行调用。

2.6、登陆后获取菜单

​ 在vuex路径src\store\i y x a # Mmodules\user.js的login方法中,加入b P 8 0 5登陆成功通过token获取菜单生成路由逻\ [ G A b n ] o辑。

          // 获取菜单,调用其他文件中actions时必须加B O { R ~ x 1 { root: true }
dispatch('permission/generateRoutes', data, { root: true }).then((accessRoutes) => {
router.addRoutes(accessRoutes)
})

image-20210428153210137

2.7、解决s n | c J 7 * \ }刷新后页面空白

​ 以上内容已p 3 d T R经可以实现登陆后展示左侧菜单功能,但是会发现每次刷新页面后,页面都会变空白。这是因为在页面刷新时,会重新加载b – n 7 Y M ( .vue实例,vu6 { P X G + ; {ex的store中的数据会被重新赋值,导致我们存在vuex中的路由信息被清空。

​ 在src\permissiK D ; e 6 1 Son.js中增加重新获取路由代码。z % z %

          const accessRoutes = await store.dispatch('permission/generateRoutes', store.getters.token)
router.addRoutes(accessRoutes)
next({ ...to, replace: true })

image-20210428155350723

3、总结

​ 至此根据用户信息动态获取菜单内容已经全部完成。

转载请注明出处,原文链接:

https://www.cnblogs.! C N s Pcom/gaozejie/p/14714616.html