VUE动态权限菜单
第一种 后台返回的是多维数组,即菜单格式以及排好// main.jsVue.prototype.routerLoad = {// 遍历添加路由bianli(arr) {return arr.map(v => {// 子菜单判断if (v.subs) {// this...
·
第一种 后台返回的是多维数组,即菜单格式以及排好
// main.js
Vue.prototype.routerLoad = {
// 遍历添加路由
bianli(arr) {
return arr.map(v => {
// 子菜单判断
if (v.subs) {
// this.menus.push(...this.bianli(v.subs))
return this.bianli(v.subs);
} else {
return {
path: "/" + v.index,
name: v.index,
// 路由地址拼接---注意动态路由对文件名的要求很高,最好名称一致
component: () =>import (`@/components/page/${v.index}/${v.index}.vue`),
meta: { title: v.title }
}
}
})
},
// 获取菜单
loadMenus() {
let userId = sessionStorage.getItem('userId')
if (userId) {
// 因为是在main.js里面,所以这里是 axios
// 掉接口获取后台返回的菜单格式
axios.get(`/api/permission/role/functions/${userId}`).then(res => {
console.log('动态路由添加成功')
console.log(res)
let menus = res.data;
// vuex中存储 菜单列表 用于页面菜单的显示
store.commit('setMenus', menus)
// flat(number) 数组拉平 number:拉平的层数,默认一层
// 由于遍历调用多次,所以返回的是多维数组,所以需要拉平
// 想要代码严谨,拉平次数可以动态添加
let routerArr = this.bianli(menus).flat(9);
// 路由添加添加
router.options.routes[1].children.push(...routerArr);
router.addRoutes(router.options.routes);
// 刷新后跳转到刷新前页面---因为路由是动态添加的,所以要保存刷新前页面的路由
if (sessionStorage.getItem('path') == '/') {
sessionStorage.setItem('path', '/dashboard')
}
// 刷新后的路由跳转
router.push({ path: sessionStorage.getItem('path') })
})
.catch(err => {
console.log("网络错误");
});
}
}
}
//使用钩子函数对路由进行权限跳转
router.beforeEach((to, from, next) => {
// 存储当前路由值,用于刷新跳转
if (to.path != '/404' && to.path != "/403") {
// 跳转时存储路由
sessionStorage.setItem('path', to.fullPath)
}
})
new Vue({
router,
store,
render: h => h(App),
created() {
// 本地存储时存储一个值,防止初始打开登陆页面时调用---可以用 token
// 主要用于页面刷新时调用
if (sessionStorage.getItem('token')) {
this.routerLoad.loadMenus()
}
}
}).$mount('#app')
-------------------------------------------------------------------------------
// Login.vue 页面
// 登陆成功后
sessionStorage.setItem('token',123465)
this.routerLoad.loadMenus()
// 跳转首页
this.$router.push('/dashboard')
-------------------------------------------------------------------------------
// store.js
import Vue from "vue"
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
menus: []
},
mutations: {
// 菜单
setMenus(state, menus) {
state.menus = menus
}
},
actions: {
},
getters: {
}
});
export default store
第二种 后台返回的是一维数组,即通过里面的父级Id值来遍历判断
// main.js
Vue.prototype.routerLoad = {
/**
* 过滤函数
*/
filterArr(arr, i) {
let obj = undefined
arr.find(item => {
if (item.id == i) {
obj = item
return true
} else if (item.subs) {
obj = this.filterArr(item.subs, i)
if (obj) {
return obj
}
}
})
return obj
},
/**
* 遍历函数
*/
arr(arr, roleTree, roleTreeObj) {
arr.find((item, index) => {
let itemObj = {
icon: item.iocn, // 菜单图标
index: item.urlPre, // 菜单列表跳转路径
title: item.name, // title
id: item.id, // 菜单id值
sort: item.sort, // 菜单排序值---菜单列表项的前后顺序
superior: item.superior // 父级菜单
}
// 最外层菜单---一级菜单
if (item.id == item.superior) {
roleTree.push(itemObj)
} else {
// 调用过滤函数查找到当前父级id在菜单数组的位置
let obj = this.filterArr(roleTree, item.superior)
// 没有匹配到时:因为后台返回的菜单顺序不同,有可能父级菜单在下面,子菜单在上面
if (!obj) {
// 存储暂时还没有遍历到的上级,以键值对的形式存储,{父级id : 子菜单列表数组}
// 判断对象中的父级id是否存在
if (!roleTreeObj[item.superior]) {
roleTreeObj[item.superior] = []
}
roleTreeObj[item.superior].push(itemObj)
} else {
// 有结果时,判断当前父级是否有子数组
if (!Array.isArray(obj.subs)) {
obj.subs = []
}
obj.subs.push(itemObj)
}
}
})
// 遍历完成,返回菜单数组和菜单对象
return { roleTree, roleTreeObj }
},
/**
* 对象遍历函数
*/
binaliObj(allObj) {
for (let key in allObj.roleTreeObj) {
let obj = this.filterArr(allObj.roleTree, key)
if (obj) {
if (!Array.isArray(obj.subs)) {
obj.subs = []
}
obj.subs.push(...allObj.roleTreeObj[key])
// 每添加一个就删除对象里面对应的值
delete allObj.roleTreeObj[key]
}
}
// for in 循环完后判断对象里面是否还有数据
if (Object.keys(allObj.roleTreeObj).length != 0) {
this.binaliObj(allObj)
}
// return allObj.roleTree
// 复杂数据类型,所以不需要return出来
return false
},
/**
* 数组排序
*/
sortArr(arr) {
arr.sort(function(a, b) {
if (a.sort > b.sort) { // a-->arr[j] b-->arr[j+1]
return 1;
} else if (a.sort == b.sort) {
return 0;
} else {
return -1;
}
})
// 多维数组,所以遍历排序
arr.forEach(item => {
if (item.subs) {
this.sortArr(item.subs)
}
});
},
// 遍历添加路由
bianli(arr) {
return arr.map(v => {
// 子菜单判断
if (v.subs) {
// this.menus.push(...this.bianli(v.subs))
return this.bianli(v.subs);
} else {
return {
path: v.index,
name: v.index.slice(1),
component: () => {
// 因为编写代码时,文件格式没写好,所以这里要进行判断
if (v.index == '/Dashboard') {
return import (`@/components/page${v.index}.vue`)
} else if (v.index == '/SI') {
return import (`@/components/page/Sim/Sim.vue`)
} else {
return import (`@/components/page${v.index}${v.index}.vue`)
}
},
meta: { title: v.title }
}
}
})
},
// 获取菜单
loadMenus() {
axios.get(`/api/common/v1.0/getMenu`).then(res => {
console.log('动态获取成功')
// 后台返回的时一维数组
// 用于保存最终生成的多维数组
let roleTree = []
// 初次遍历,返回菜单数组和父级id组成的对象
let allObj = this.arr(res.data.data, roleTree, {})
console.log(allObj)
// 再次=遍历,用于解决菜单对象,最后返回一个完整版的菜单数组
this.binaliObj(allObj)
// 排序
this.sortArr(allObj.roleTree)
// vuex中存储 菜单列表 用于页面菜单的显示
store.commit('setMenus', allObj.roleTree)
// 路由添加
let routerArr = this.bianli(allObj.roleTree).flat(9)
router.options.routes[1].children.push(...routerArr);
router.addRoutes(router.options.routes);
console.log(router)
// 刷新后跳转到刷新前页面 --- 这个if判断好像有点多余,因为路由里面有了重定向
if (sessionStorage.getItem('path') == '/') {
sessionStorage.setItem('path', '/dashboard')
}
// 刷新后的路由跳转
router.push({ path: sessionStorage.getItem('path') })
})
.catch(err => {
alert("菜单错误");
});
}
}
//使用钩子函数对路由进行权限跳转
router.beforeEach((to, from, next) => {
// 存储当前路由值,用于刷新跳转
if (to.path != '/404' && to.path != "/403") {
// 跳转时存储路由
sessionStorage.setItem('path', to.fullPath)
}
})
new Vue({
router,
store,
render: h => h(App),
created() {
// 本地存储时存储一个值,防止初始打开登陆页面时调用
// 主要用于页面刷新时调用
if (sessionStorage.getItem('token')) {
this.routerLoad.loadMenus()
}
}
}).$mount('#app')
-------------------------------------------------------------------------------
// Login.vue 页面
// 登陆成功后
sessionStorage.setItem('token',123465)
this.routerLoad.loadMenus()
// 跳转首页
this.$router.push('/')
-------------------------------------------------------------------------------
// store.js
import Vue from "vue"
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
menus: []
},
mutations: {
// 菜单
setMenus(state, menus) {
state.menus = menus
}
},
actions: {
},
getters: {
}
});
export default store
/**
* 第二中情况还有一种解决方法:
* 1. 先通过 id == parentId 来获取最外层菜单,放到一个数组里
* 2. 然后遍历两个数组,通过 id == parentId,匹配成功就 push 进当前的数组项
* 3. 按照步骤二循环遍历,直至后台返回的数组里面没有数据
*/
最后菜单列表渲染页面用 this.$store.state.menus 获取菜单列表就行
更多推荐
已为社区贡献2条内容
所有评论(0)