故心故心故心故心小故冲啊
路由拦截
//分析
// 当前是否在登录页面 =>在=>放行
// 不在 =>没有登录或者已经登录了的
// 已经登录了(有角色信息的) =>放行
// 已经登录了(没有角色信息==>进行了刷新操作(或者第一次进去))=> 获取角色信息
// 没有登录的 =>返回登录页
router.beforeEach(async (to, from, next) => {
//判断当前是否在登录页面
if (to.path == '/login') {
// 如果在=>放行
// console.log('在登录页,直接放行');
next();
}
//如果不在
else {
// 判断是否有角色信息(因为有可能是已经登录进来的了) 看是否能在store中获取到角色信息
var R = store && store.getters.roles && store.getters.roles.length > 0;
if (R) {
//有角色 => 放行
// console.log('有角色');
next();
}
//没有角色呢?
else {
// 没有就获取角色---用户进行了刷新操作
//获取角色 通通actions 发送请求获取 await需要获取到角色后在进行下面操作
var { role_name } = await store.dispatch('userInfo');
console.log(role_name);
//2.0vuex来处理路由,把角色名传过去
let asyncRoutes = await store.dispatch('GETROUTES', [role_name]);
//3.0动态添加路由(asyncRoutes表示经过不同角色的路由)
router.addRoutes(asyncRoutes);
//若是获取到角色
if (role_name) {
next();
}
//若是获取不到角色
else {
// console.log('无角色信息,返回登录页');
//无角色信息,返回登录页
next({ path: '/login' })
}
}
}
})
存储角色信息–vuex
import Vue from 'vue'
import Vuex from 'vuex'
import { userInfo, logout } from '@/api/interface'
Vue.use(Vuex)
const state = {
//存储角色信息的
roles: []
};
const getters = {
//获取state中roles
roles: state => state.roles
};
const mutations = {
//同步的mutations 专门用于修改state中的状态
//data就是actions中data中获取的角色信息的
setRoles: (state, data) => state.roles = data
};
const actions = {
//异步的 通过$store.dispath('actions名字')获取
//登录
userInfo({ commit }) {
return new Promise((resolve, reject) => {
//发送请求获取角色信息(用户详情)
userInfo().then(res => {
console.log(res);
let { data } = res.data.data;
//只能通过mutations来改变状态
commit('setRoles', data[0][0].role_name)
// console.log(data[0][0]);
resolve(data[0][0]);
}).catch(err => {
reject(err);
})
})
},
// 退出 需要清除角色信息
logout({ commit }) {
return new Promise((resolve, reject) => {
//发送请求获取角色信息(用户详情)
logout().then(() => {
//设置为空 ,清除
commit('setRoles', [])
resolve();
}).catch(err => {
reject(err);
})
})
}
};
export default {
state,
getters,
mutations,
actions
}
通过角色信息动态添加路由
import Vue from 'vue'
import Vuex from 'vuex'
//引入常规路由配置 和 动态路由配置
import { constantRoutes, asyncRoutes } from '@/router'
Vue.use(Vuex)
function filterAsyncRouter(asyncRoutes, rolesName) {
var filterRouter = asyncRoutes.filter(item => {
//通过判断不是拥有该角色,来过滤出对应的路由
return item.meta && item.meta.roles && rolesName.some(v => item.meta.roles.includes(v))
})
return filterRouter;
}
const state = {
//这个是经过处理的路由,不同角色所产生的的路由
routes: [],
};
const getters = {
routes: state => state.routes
};
const actions = {
//异步操作 =>需求不同角色所产生的的路由
GETROUTES({ commit }, rolesName) {
return new Promise((resolve) => {
// console.log(constantRoutes);
//1.0获取到home
var _routes = []; //接收home
var home = constantRoutes.filter(v => v.path == '/home')[0];
//清除home的children
home.children = []; //清除
//2.0为home添加children(需要判断当前角色)
if (rolesName.includes('administrator')) { //是否是管理员
//是管理员,那动态配置所有路由
console.log('管理员');
home.children = asyncRoutes;
} else {
//不是管理员
//通过角色过滤出路由
console.log('非管理员');
let filterRouter = filterAsyncRouter(asyncRoutes, rolesName);
console.log(filterRouter);
home.children = filterRouter;
}
//因为addRouter接受的参数是一个数组
_routes = [home] || [];
console.log(_routes)
commit('SET_ROUTES', _routes);
resolve(_routes);
})
}
};
const mutations = {
//把从actions获得的路由修改state中的路由
SET_ROUTES: (state, routes) => state.routes = routes
};
export default {
state,
getters,
actions,
mutations
}
通过vuex存储的路由信息来动态渲染路由
引入了子组件navItem 通过:item="route 实行渲染
index.vue
<template>
<!-- 侧边导航栏 -->
<el-aside width="200px">
<el-menu default-active="$route.path" router exact text-color="#fff" active-text-color="skybule" unique-opened collapse-transition>
<navItem v-for="route in routes[0].children" :key="route.path" :item="route" />
</el-menu>
</el-aside>
</template>
<script>
import { mapGetters } from "vuex";
import navItem from "./navItem";
export default {
computed: {
...mapGetters(["routes"])
},
components: {
navItem
}
};
</script>
navItem.vue
<template>
<div>
<el-menu-item :index="item.path" v-if="!item.children">
<span slot="title">{{item.meta.title}}</span>
</el-menu-item>
<!-- 有子级 -->
<el-submenu :index="item.path" v-else>
<template slot="title">
<span slot="title">{{item.meta.title}}</span>
</template>
<navItem v-for="child in item.children" :key="child.path" :item="child" />
</el-submenu>
</div>
</template>
<script>
export default {
name: "navItem",
props: ["item"]
};
</script>
<style scoped>
</style>