1、前言
? vue-element-admin是一個純前端的框架,左側選單是根據路由生成的,實際開發中經常需要根據當前登陸人員的資訊從后端獲取選單進行展示,本文將詳細介紹如何實作該功能,
2、詳解
? 整體思路為:登陸 > 成功后根據用戶資訊獲取選單 > 根據選單生成路由資訊
2.1、新增asyncRoutes路由
? 在vue-router路徑src\router\index.js中新增asyncRoutes陣列,用來存放后端獲取的選單對應的路由資訊,
export const asyncRoutes = [
{ path: '*', redirect: '/404', hidden: true }
]

constantRoutes和asyncRoutes的區別
constantRoutes:不需要動態判斷權限的路由,如登錄頁、404等通用頁面,
asyncRoutes:需求動態判斷權限并通過addRoutes動態添加的頁面
2.2、新建permission.js檔案
? 在vuex路徑src\store\modules\permission.js下新建permission.js檔案,該操作為最重要的一步,主要是從后端查詢選單并生成路由,
import { asyncRoutes, constantRoutes } from '@/router'
import { fetchUserMenuList } from '@/api/user'
import Layout from '@/layout'
/**
* 靜態路由懶加載
* @param view 格式必須為 xxx/xxx 開頭不要加斜杠
* @returns
*/
export const loadView = (view) => {
return (resolve) => require([`@/views/${view}.vue`], resolve)
}
/**
* 把從后端查詢的選單資料拼裝成路由格式的資料
* @param routes
* @param data 后端回傳的選單資料
*/
export function generaMenu(routes, data) {
data.forEach(item => {
const menu = {
path: item.url,
component: item.component === '#' ? Layout : loadView(item.component),
hidden: item.status === 0, // 狀態為0的隱藏
redirect: item.redirect,
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 actions = {
generateRoutes({ commit }, token) {
return new Promise(resolve => {
// 通過token從后端獲取用戶選單,并加入全域狀態
fetchUserMenuList(token).then(res => {
const menuData = https://www.cnblogs.com/gaozejie/archive/2021/04/28/Object.assign([], res.data)
const tempAsyncRoutes = Object.assign([], asyncRoutes)
const accessedRoutes = generaMenu(tempAsyncRoutes, menuData)
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
}).catch(error => {
console.log(error)
})
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
2.3、在vuex中注冊permission模塊
? 如果使用的是vue-element-admin請跳過此步,因為它在src\store\index.js中自動注冊了src\store\modules下的所有模塊,如果你使用的是vue-element-template,可以參考admin,將index.js檔案改造一下,也可以手動import一下,
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
Vue.use(Vuex)
// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context('./modules', true, /\.js$/)
// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
// set './app.js' => 'app'
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = https://www.cnblogs.com/gaozejie/archive/2021/04/28/modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const store = new Vuex.Store({
modules,
getters
})
export default store
2.4、在getters中增加路由狀態
? 在vuex路徑src\store\getters.js添加menusRoutes狀態
menusRoutes: state => state.permission.routes

2.5、修改選單生成資料來源
? 在路徑src\layout\components\Sidebar\index.vue修改routes資料來源,原來資料源是路由,改為從vuex中獲取,
routes() {
// return this.$router.options.routes
return this.$store.getters.menusRoutes
},

? 至此,從后端獲取選單資料到頁面展示的邏輯已經完畢,下面開始在登陸后進行呼叫,
2.6、登陸后獲取選單
? 在vuex路徑src\store\modules\user.js的login方法中,加入登陸成功通過token獲取選單生成路由邏輯,
// 獲取選單,呼叫其他檔案中actions時必須加 { root: true }
dispatch('permission/generateRoutes', data, { root: true }).then((accessRoutes) => {
router.addRoutes(accessRoutes)
})

2.7、解決重繪后頁面空白
? 以上內容已經可以實作登陸后展示左側選單功能,但是會發現每次重繪頁面后,頁面都會變空白,這是因為在頁面重繪時,會重新加載vue實體,vuex的store中的資料會被重新賦值,導致我們存在vuex中的路由資訊被清空,
? 在src\permission.js中增加重新獲取路由代碼,
const accessRoutes = await store.dispatch('permission/generateRoutes', store.getters.token)
router.addRoutes(accessRoutes)
next({ ...to, replace: true })

3、總結
? 至此根據用戶資訊動態獲取選單內容已經全部完成,
轉載請注明出處,原文鏈接:
https://www.cnblogs.com/gaozejie/p/14714616.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/281177.html
標籤:其他
上一篇:index詳解
