admin管理员组文章数量:1633987
1.什么是动态路由?
首先我们需要知道什么是动态路由,或者说什么是菜单权限?
在一个系统中,每一个用户都拥有对应权限允许做的事情,当我们设计者不想暴露更多的操作给用户的时候,我们就可以利用后端检查用户所对应的权限,然后返回对应的菜单列表给前端,限制用户更多的操作。
2.实现动态路由的步骤
1.在我们简单了解动态路由的概念之后,在VueRouter的api中提供了一个addRoute的方法,我们可以添加对应的路由进入Vue中的路由表中,这样我们就可以访问到对应的页面了。
2.利用axios传递uid到后端查询数据库中的用户表,同时关联查询路由表中对应的路由信息列表,最后返回给前端重新构造成tree模型。
3.将得到的tree模型构造成路由形式的新的tree模型。
4.利用第一点讲到的addRoute方法将模型加入路由表中。
5.最后利用嵌套组件形式展示最终的菜单列表。
3.具体实现
1.建表
(1)首先需要建立一个用户表(user),除了基本的用户信息,还要有一个用户状态(int类型)来代表该用户所具有的权限。
(2)接着建立路由表(router),路由表需要对应的路由id,以及父路由id,路由名称,路由路径,路由链接,以及路由标题。
当路由是子路由时,父路由id则不为0,应该对应为父路由的id
当路由为一级路由时,路由链接应该为null,因为此时可以通过路由名称来访问即可
当路由为子路由时,注意路由路径不能加’/',否则代表根目录下的路由级别
(3)建立一个中间表(user_router),用户表通过ustatus来访问到对应路由信息。
如上表所示可以得知用户对于所获得的路由信息应该如下:
ustatus为1获取到的路由id列表为:1,2,3,4
ustatus为2获取到的路由id列表为:5,6,7,8
ustatus为3获取到的路由id列表为:1,2,4,5,6,7,8
2.访问数据库获取到对应用户的路由列表
在这里笔者就不再展示如何获取列表信息了,利用mybatis框架直接映射出用户对应的路由信息列表即可。
3.前端通过axios传递uid到后端获取到路由列表
(1)访问后端接口。
async getRouter({ state ,commit}) {
await axios({
method: "post",
url: "/Springmvc/getRouters",
data: qs.stringify({
uid: state.uid
})
})
.then((res) => {
state.routerList = RouterListFormat(res.data.routerList)//转为tree模型
})
.catch((err) => {
console.log(err.message);
});
commit('setAuth',true)//只有获取到返回值的时候才修改用户权限
}
注意:该方法是封装在vuex中的actions的,同时我们可以通过async、await来保证只有在路由信息列表的获取后,才执行修改用户当前的菜单权限。
(2)当前端接收到路由列表信息时,如下图所示。
此时我们前端获取到的都是一级路由结构,不存在tree模型,所以接下来我们需要进入转换。
(3)利用递归算法进行转换。
function RouterListFormat(data){
let parents = data.filter(p => p.pid===0),
children = data.filter(c => c.pid != 0)
dataTotree(parents,children)
//递归函数
function dataTotree(parents,children){
parents.map((p)=>{
children.map((c,index)=>{
if(c.pid === p.rid){//如果相同,拷贝children一个新的数组c1
let c1 = Object.assign([],children)
c1.splice(index,1)//删除当前元素,获取除当前元素之外的所有子路由元素
dataTotree([c],c1);//继续递归
if(p.children){//如果该结点已经存在孩子,则直接加入孩子
p.children.push(c)
}else{//如果该结点不存在孩子,则让该结点的孩子等于数组c
p.children = [c]
}
}
})
})
}
return parents
}
此算法的核心就是,先把路由分别父路由和子路由两部分进行递归,接着不断在子路由中重新找到一个结点充当父路由,把其余部分当成新的子路由列表进行递归,直至最后,返回父路由。
(4)进一步转化为路由结构的tree模型
//转化为路由表格式
function generateRouter(UserRouter){
let newRouters = UserRouter.map((r)=>{
let routes = {
path:r.path,
name:r.name,
component:()=>import(`@/views/${r.name}.vue`)//利用字符串模板拼接
}
if(r.children){//如果该结点有孩子,则继续递归
routes.children = generateRouter(r.children)
}
return routes
})
return newRouters
}
转为成路由结构也是利用递归算法,核心就是进行自顶向下遍历,最后把整个tree模型都遍历完,得到一个具有路由结构的tree模型。
注意:利用map遍历方法的特点,能够返回一个新的对象,最后生成一个新的数组。
(5)利用全局路由守卫作为入口
router.beforeEach(async(to,from,next) =>{
if(!store.state.user.hasAuth){//如果还没有权限
await store.dispatch('user/getRouter')
const newRoutes = generateRouter(store.state.user.routerList)
newRoutes.map((item)=>{
router.addRoute(item)
})
next({path:to.path})//前往当前输入的链接所在的页面
}else{//当权限存在,直接放行
next()
}
})
(6)最后建立对应路由名称的组件即可,即创建Course.vue、Student.vue…
注意需要在父组件写路由视图
4.利用嵌套组件展示路由列表
创建MenuItem.vue
<template>
<div>
<ul v-if="item.children && item.children.length>0">
<li>
<router-link :to="item.link || item.path" >{{item.title}}</router-link>
<div v-for="(c,index) in item.children" :key="index">
<MenuItem :item="c"/>
</div>
</li>
</ul>
<ul v-else>
<router-link :to="item.link || item.path" >{{item.title}}</router-link>
</ul>
</div>
</template>
<script>
export default {
name:'MenuItem',
props:{
item:Object
}
}
</script>
5.测试结果
1.当uid为1时
2.当uid为2时
3.当uid为3时
4.点击菜单列表,进行路由跳转
此时的地址栏地址为:
测试结果正确。
注意:
1.当进行页面刷新时,因为我们是通过判断用户是否有权限来实现的,所以每一次的刷新都会从后端返回一个路由信息列表。
2.对于从后端获取路由信息列表的时候,我们需要完善对应的逻辑,比如前端可能存在用户没有登录的情况,这时候我们就只加载出静态路由即可。或者当用户为黑户的时候,我们后端需要对其进行拦截。
这是本人第一次写博客,如果有不足请多多包涵。
版权声明:本文标题:关于vue的动态路由或菜单权限问题的解决方案 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1729175960a1188720.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论