需求:用戶登錄后獲取相應(yīng)的菜單權(quán)限禾乘,這里已知后臺獲取的菜單樹
這里介紹兩種方式:
1、根據(jù)從后臺獲取的路由路徑動態(tài)注冊路由(import到項(xiàng)目)蒲稳,在前端配置菜單權(quán)限時需提交路由的路徑給后臺伍派;
2、前端代碼中將所有的路由路徑注冊好(全部import到項(xiàng)目)诉植,由于路由全部注冊好了,根據(jù)后臺返回的菜單顯示即可舌稀;但這樣在地址欄輸入路由還是可以訪問到灼擂,所以前端配置菜單權(quán)限時需要給后臺提交相應(yīng)的接口權(quán)限,用戶登錄后沒有這個菜單的接口權(quán)限則輸入地址欄也無權(quán)訪問潮罪,保證正確性领斥。
兩種方式的區(qū)別:
第一種是通過后臺獲取菜單之后去注冊路由沃暗,那么地址欄輸入路由就會報404
第二種是全部注冊好路由,地址欄輸入不會報404嚼黔,這時候需要控制接口權(quán)限
方式一:動態(tài)注冊路由
loadingRoutes.js
/*
動態(tài)注冊路由
頁面全在views文件夾下
如:
import page1 from './views/page1.vue'
import page2 from './views/page/page2.vue'
*/
export default (name) => () => import(`@/views/${name}.vue`)
menuUtils.js
// 引入注冊路由方法
import loadingRoutes from './loadingRoutes'
export default (routers, data) => {
//轉(zhuǎn)換服務(wù)端菜單數(shù)據(jù),拿到自己想要的字段唬涧,比如這里的路由路徑component (或者其他的key)
generaMenu(routers, data)
}
function generaMenu(routers, data) {
if (data) {
data.forEach((item) => {
//這里在和后臺規(guī)定如果是按鈕權(quán)限component字段為'/' 碎节,權(quán)限按鈕為彈出框,沒有路由
if (item.path == "/") {
return false;
}
let menu = Object.assign({}, item);
if (menu.component == "home") {
menu.component = require("@/views/Home.vue");
menu = Object.assign({redirect: item.children?item.children[0].path:"/main"}, menu);
} else {
// 注冊加載相應(yīng)路由
menu.component = loadingRoutes (menu.component)
}
//有子菜單
if (item.leaf == "true") {
menu.children = [];
generaMenu(menu.children, item.children)
}
// 將菜單push進(jìn)路由
routers.push(menu)
})
}
}
home.vue
created() {
//這里沒有直接使用this.$router.options.routes,是因?yàn)閍ddRoute的路由規(guī)則胎撇,在這里this.$router.options.routes獲取不到
//另外在開發(fā)的時候殖氏,可能由于是熱部署,也會不斷重復(fù)的給nodes添加元素雅采,造成導(dǎo)航條有重復(fù)的婚瓜,簡單解決,可以設(shè)置一個開關(guān)
let isLoadNodes = sessionStorage.getItem('isLoadNodes');
if (!isLoadNodes) {
let menuInfo = sessionStorage.getItem('menuInfo');
if (menuInfo) {
let data = JSON.parse(window.sessionStorage.getItem('menuInfo'));
this.nodes.push(...data);
sessionStorage.setItem('isLoadNodes', 'true')
} else {
//this.$api.getMenus({roleId: getCookie('property_roleId')}).then((res) => {
this.$api.getMenus({roleId: sessionStorage.getItem('property_roleId')}).then((res) => {
if (this.$util.checkCode(this, res)) {
this.nodes.push(...res.data);
sessionStorage.setItem('isLoadNodes', 'true')
}
});
}
}
},
routes.js
const router = new Router({
mode: 'history',
routes
});
// 引入MenuUtils
import MenuUtils from '@/scripts/common/MenuUtils'
let data = JSON.parse(window.sessionStorage.getItem('menuInfo'))
if (data) {
//這里是防止用戶手動刷新頁面席函,整個app要重新加載,動態(tài)新增的路由冈涧,會消失,所以需要重新add一次
// 或者通過vuex保存菜單营曼,重新賦值 這里不做說明
let routes = [];
MenuUtils(routes, data);
router.addRoutes(routes);
window.sessionStorage.removeItem('isLoadNodes');
}
方式二:注冊好全部路由愚隧,后臺控制接口訪問權(quán)限
方式二其實(shí)更簡單,由于路由全部注冊好了录煤,通過后臺返回的菜單樹進(jìn)行顯示即可荞胡,這里不做詳細(xì)說明泪漂。
如果采用vuex保存菜單歪泳,注意刷新的時候重新獲取菜單露筒。
本篇文章偏向于說明動態(tài)獲取菜單的思想,有什么不足的地方或疑問歡迎指出來慎式,謝謝大家~