vue 动态路由权限管理(浓缩代码简单版)
一、首先在main.js做路由守卫,不能先跳转路由页面,在页面中向后端获取路由配置文件。*相关补充:权限管理一般放到项目的最后时间来做,最开始路由配置信息前端都是写死,做权限管理的时候,需要将路由配置发给后端,让后端判断该显示哪些菜单,再返回给前端,不能前端判断,考虑到后端接口返回的值是可以被拦截修改的。*main.js添加如下代码:import store from "./store";/**动
一、首先在main.js做路由守卫,不能先跳转路由页面,在页面中向后端获取路由配置文件。
*相关补充:权限管理一般放到项目的最后时间来做,最开始路由配置信息前端都是写死,做权限管理的时候,需要将路由配置发给后端,让后端判断该显示哪些菜单,再返回给前端,不能前端判断,考虑到后端接口返回的值是可以被拦截修改的。*
main.js添加如下代码:
import store from "./store";
/**动态路由 */
const whiteList = ['Login', 'Index'];//默认可以跳转的路由。
let asyncRouterFlag = 0;
router.beforeEach(async(to, from, next) => {
const token = localStorage.getItem('admin_systemToken');
document.title = to.meta.title; //设置标题
if (whiteList.indexOf(to.name) > -1) { //查询是否是默认可以跳转的路由
if (to.path == '/login') { //如果是去登录页面直接进入
next();
} else {
if (!token) { //没有登录,进入登录页
next('/login');
} else {
if (!asyncRouterFlag) { //进入非权限页面同时获取权限菜单。
asyncRouterFlag++
await store.dispatch('router/SetAsyncRouter')
}
next();
}
}
}else{ //判断是否满足权限
if(token){
// 添加flag防止多次获取动态路由和栈溢出
if (!asyncRouterFlag) {
asyncRouterFlag++;
//同步调用获取菜单方法
await store.dispatch('router/SetAsyncRouter') //发请求获取菜单,并将菜单设置到vuex中,
const asyncRouters = store.getters['router/asyncRouters'];
//循环后动态添加路由,addRoutes方法好像不能用了
asyncRouters.map(asyncRouter => {
router.addRoute(asyncRouter)
})
next({ ...to, replace: true })
} else {
next()
}
}else{
next({
path: '/login',
// query: {
// redirect: document.location.hash
// }
})
}
}
})
二、获取路由配置文件。路由配置文件基本上跟后台的菜单结构都差不多,所以获取了路由配置文件的时候,就不需要再获取菜单了。那么路由配置文件最好是写在vuex中。
1.新建一个vuex模块,并使用。
store/index.js:
import Vue from 'vue'
import Vuex from 'vuex'
import router from './router/index.js'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {},
modules: {
router
}
})
2.路由配置文件相关处理。
store/router/index.js:
export default {
namespaced: true,
state: {
//动态路由配置
asyncRouters:[]
},
mutations: {
// 设置动态路由
setAsyncRouter(state, asyncRouters) {
state.asyncRouters = asyncRouters
}
},
actions: {
//获取菜单
async SetAsyncRouter({ commit }) {
//获取菜单的路由配置,并配置
var list=[
{
path: "#",
component: () =>import("@/views/layout/index.vue"),
meta: {
icon: 'el-icon-message'
},
children: [{
path: "/userManage/userList",
name: "userManageUserList",
component: (resolve) => require(['@/views/userManage/userList/index.vue'], resolve),
meta: {
title: "用户列表",
icon: 'el-icon-position'
}
}]
},
{
path: "#",
component: () =>import("@/views/layout/index.vue"),
meta: {
icon: 'el-icon-message'
},
children: [{
path: "/systemConfig/adminUser",
name: "systemConfigAdminUser",
component: (resolve) => require(['@/views/systemConfig/adminUser/index.vue'], resolve),
meta: {
title: "后台用户",
icon: 'el-icon-position'
}
}]
},
{
path: "#",
component: () =>import("@/views/layout/index.vue"),
meta: {
icon: 'el-icon-message'
},
children: [{
path: "/systemConfig/roleManage",
name: "systemConfigRoleManage",
component: (resolve) => require(['@/views/systemConfig/roleManage/index.vue'], resolve),
meta: {
title: "角色管理",
icon: 'el-icon-position'
}
}]
},
{
path: "#",
component: () =>import("@/views/layout/index.vue"),
meta: {
icon: 'el-icon-message'
},
children: [{
path: "/systemConfig/otherConfig",
name: "systemConfigOtherConfig",
component: (resolve) => require(['@/views/systemConfig/otherConfig/index.vue'], resolve),
meta: {
title: "其他参数配置",
icon: 'el-icon-position'
}
}]
}];
//添加404页面,这个只能在路由最后添加。
list.push({
path: '/404',
name: '404',
hidden: true,
meta: {
title: '迷路了*。*',
},
component: () =>import("@/views/error/index.vue"),
},{
path: "*",
redirect: "/404"
},);
commit('setAsyncRouter',list);
}
},
getters: {
//获取动态路由
asyncRouters(state) {
return state.asyncRouters
},
}
}
说明:list的数据等于后端返回给前端的数据,大家使用的时候需要调后端api获取,我这里直接写死,考虑到这里还会有一些判断,为了让大家更清楚看懂。
注意:
1.404页面必须放到最后添加,不然会出现奇怪的问题。
2.main.js文件使用了router.beforeEach,其他任何文件就不能再使用了,不能会进行双重判断,出现一些异常问题。
三、静态路由配置文件(参考)。
const routes = [{
path: "/",
redirect: '/index'
},
{
path: "/login",
name: "Login",
// component: (resolve) => require(['@/views/login/index.vue'], resolve),
component: () =>import("@/views/login/index.vue"),
meta: {
title: "登录"
}
},
{
path: "/index",
component: Layout,
children: [{
path: "/index",
name: "Index",
component: (resolve) => require(['@/views/index/Index.vue'], resolve),
meta: {
title: "首页",
icon: 'el-icon-s-home'
}
}]
},
];
四、登录后需要干什么(参考)。
登录后,代码:
//登录
login({username,password}){
let res = this.$api.login({
account:username,
password:password
}).then(res=>{
if (res.code === 200) {
this.$message({type: 'success',message: res.msg});
localStorage.setItem('admin_systemToken', res.data.api_key);
this.$router.push('/');
} else {
this.$message({type: 'error',message: res.msg});
}
}).catch(err=>{
console.log(err);
});
}
存储自己的token。
五、token过期,退出登录切换账号我们需要清除已经注册的路由,防止其他用户获得到已经注册好了的路由。
1.退出登录,跳转登录页面,并进行一次刷新操作:
router.replace({path: '/login'});
window.location.reload();
token过期时的请求拦截,如何刷新?
2.考虑到请求有可能是多个,就有可能造成多个无限刷新操作,这里需要判断一下当前页面是否在登录页面。
代码:注意:我的判断代码还没有写哈,根据自己的情况来判断重复跳转,重复刷新。
service.interceptors.response.use((res) => {
console.log(res, '我是拦截')
// if(res.)
nprogress.done()
return res.data
}, err => {
let status = err.response.status
if (err.response && err.response.status) {
console.log(err.response)
if (status == 401) {
Message.error('登录失效,请刷新后重试')
router.replace({path: '/login'});
window.location.reload();
}
}
return Promise.reject(err.response)
})
3.注意检查登录页面是否有请求会出现token过期的状态码,如果有,跟后端沟通给其他的状态码,防止登录页无限刷新。
更多推荐
所有评论(0)