效果展示
登录页面
user登录
admin登录
实现原理
前端请求API接口后台根据登录不同的用户返回相应的菜单格式,前端存储到Vuex中,router定义所有的路由,在路由中判断请求过来的菜单数据跟router中定义的路由进行对比,相同则动态添加到路由中。
src目录展示
src目录中各目录代码
mock/index.vue
- mock安装:
- npm install mockjs
- main.js中引入mock
- 代码展示:
import mockJS from 'mockjs';
const users = [
{
id: 1,
username: 'user',
password: '123456',
token: 'userToken',
role: 'user',
},
{
id: 2,
username: 'admin',
password: '123456',
token: 'adminToken',
role: 'admin',
}
]
const roles = {
user: [
{
id:'1',
authName:"user 1",
path:'home'
},
{
id:'2',
authName:"user 2",
path:'home2'
},
{
id:'3',
authName:"user 3",
path:'home3'
},
],
admin: [
{
id:'1',
authName: '高级菜单',
children: [
{
id:'11',
authName: 'admin 1',
path: 'admin',
},
{
id:'12',
authName: 'admin 2',
path: 'admin2',
}
]
},
{
id:'2',
authName:"admin 3",
path:'admin3'
},
]
}
// 用户登录
mockJS.mock('/login', 'post', option => {
const { username, password } = JSON.parse(option.body)
const user = users.find(item => {
return item.username === username && item.password === password
})
return user
})
// 用户权限信息
mockJS.mock('/roles', 'post', option => {
const {name}=JSON.parse(option.body)
// console.log(option.body);
// console.log(JSON.parse(option.body));
console.log(name);
return roles[name]
})
router/index.vue
import Vue from "vue";
import VueRouter from "vue-router";
import store from '../store'
Vue.use(VueRouter);
const routes = [
{
path: "/",
redirect: "/index",
component: () => import("@/views/layout"),
children: [
{
path:'/index',
component:()=>import('@/views/index')
}
],
},
{
path: "/login",
component: () => import("@/views/login"),
},
];
//定义所需的所有路由
const home = {
path:'/home',
component:()=>import('@/views/home')
}
const home2={
path:'/home2',
component:()=>import('@/views/home2')
}
const home3={
path:'/home3',
component:()=>import('@/views/home3')
}
const admin={
path:'/admin',
component:()=>import('@/views/admin')
}
const admin2={
path:'/admin2',
component:()=>import('@/views/admin2')
}
const admin3={
path:'/admin3',
component:()=>import('@/views/admin3')
}
const ruleList = {
home,home2,home3,admin,admin2,admin3
}
//定义动态添加路由的方法
export function initRoutes() {
const currentRoutes = router.options.routes
const menuList = store.state.list
menuList.forEach(item=>{
if(item.children){
item.children.forEach(key=>{
if(key.path){
currentRoutes[0].children.push(ruleList[key.path])
}
console.log(ruleList[key.path]);
})
}else{
if(item.path){
currentRoutes[0].children.push(ruleList[item.path])
}
}
})
//便利当前路由动态添加
for(let i=0,length=currentRoutes.length;i<length;i+=1){
const element=currentRoutes[i]
router.addRoute(element)
}
}
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
//前置路由守卫
router.beforeEach((to,from,next)=>{
if(to.path === '/login'){
next()
}else{
let token = sessionStorage.getItem('token')
if(!token){
next('/login')
}else{
next()
}
}
})
export default router;
store/index.vue
- Vuex刷新防止数据丢失
- 安装 vuex-persistedstate
npm install --save vuex-persistedstate
- 配置
import Vue from 'vue' import Vuex from 'vuex' //1.引入vuex-persistedstate import createPersistedState from "vuex-persistedstate"; Vue.use(Vuex) export default new Vuex.Store({ state: { }, getters: { }, mutations: { }, actions: { }, modules: { }, //2.配置项 plugins: [createPersistedState()] })
- 代码展示
import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from "vuex-persistedstate";
Vue.use(Vuex)
export default new Vuex.Store({
state: {
user:{},
list:[],
},
getters: {
},
mutations: {
setUser(state,value){
state.user=value
},
setList(state,value){
state.list=value
},
},
actions: {
},
modules: {
},
plugins: [createPersistedState()]
})
views各页面展示
admin,home,index/index.vue
页面一样展示的数据不同
<template>
<div>
<h2>home</h2>
{{ $store.state.user }}
</div>
</template>
<script>
export default {
}
</script>
<style></style>
layout/index.vue
<template>
<el-container>
<el-aside width="200px">
<el-row class="tac">
<el-col :span="12">
<el-menu default-active="2" class="el-menu-vertical-demo" router>
<el-menu-item index="/index">
<i class="el-icon-menu"></i>
<span slot="title">index</span>
</el-menu-item>
<!-- 遍历菜单 -->
<template v-for="item in menuList">
<!-- 含有子菜单 -->
<template v-if="item.children && item.children.length > 0">
<el-submenu
:index="item.id"
:key="item.id"
>
<template slot="title">
<i class="el-icon-location"></i>
<span>{{ item.authName }}</span>
</template>
<el-menu-item
:index="'/' + subItem.path"
v-for="subItem in item.children"
:key="subItem.index"
>
<template>
<span>{{ subItem.authName }}</span>
</template>
</el-menu-item>
</el-submenu>
</template>
<!-- 不含有子菜单 -->
<template v-else>
<el-menu-item :index="item.path" :key="item.id">
<i :class="item.icon"></i>
<span slot="title">{{ item.authName }}</span>
</el-menu-item>
</template>
</template>
</el-menu>
</el-col>
</el-row>
</el-aside>
<el-container>
<el-header
>Header
<el-button @click="exit">exit</el-button>
</el-header>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</template>
<script>
import { mapState } from "vuex";
import { initDyamicRoutes } from "@/router";
export default {
name: "Layout",
data() {
return {
menuList: [],
};
},
computed: {
...mapState(["list", "user"]),
},
created() {
initDyamicRoutes();
this.menuList = this.list;
},
methods: {
exit() {
this.$store.commit("setList", []);
this.$store.commit("setUser", {});
sessionStorage.removeItem('token')
this.$router.push("/login");
},
},
};
</script>
<style>
/* ------------ Container 布局容器 全铺 -----------*/
.el-container {
height: 100vh;
}
.el-row,
.el-col {
height: 100%;
}
/* ----------------------------------------- */
.el-header,
.el-footer {
background-color: #b3c0d1;
}
.el-aside {
background-color: #d3dce6;
}
.el-main {
background-color: #e9eef3;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
min-height: 100%;
}
</style>
login/index.vue
- 页面展示
- 代码展示
<template>
<div>
<h2>login</h2>
<el-button @click="userBtn">mock test user login</el-button>
<el-button @click="adminBtn">mock test admin login</el-button>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: "home",
data() {
return {
username:'',
password:'123456'
};
},
methods:{
userBtn(){
this.username='user',
this.mockTestFn()
},
adminBtn(){
this.username='admin',
this.mockTestFn()
},
mockTestFn(){
this.axios({
method:'POST',
url:'/login',
data:{
username:this.username,
password:this.password
}
}).then(
res=>{
if(res.status==200){
this.$store.commit('setUser',res.data)
sessionStorage.setItem('token',res.data.token)
this.axios({
method:'POST',
url:'/roles',
data:{
name: res.data.role
}
}).then(
res=>{
console.log(res);
this.$store.commit('setList',res.data)
this.$message('success')
this.$router.push('/index')
}
)
}
}
)
}
}
};
</script>
<style></style>