一、从接口获取菜单、路由
登录了,登录人的信息会传给后台,后台就会判断,这个登录的人是什么角色,这个角色有什么权限或者说路由、菜单数据。
这里采用的mock进行的后台数据的模拟
mock里面的数据格式
模拟数据:
export default [
{ name:'Home',tilte: '首页', icon: 'el-icon-s-home', path: '/home' ,component:'Home'},
{ name:'Menu',tilte: '菜单管理', icon: 'el-icon-menu', path: '/menu' ,component:'Menu'},
{ name:'Department',tilte: '部门管理', icon: 'el-icon-s-help', path: '/department',component:'Department'},
{ name:'Role',tilte: '角色管理', icon: 'el-icon-user-solid', path: '/role' ,component:'Role'},
{ name:'Order',tilte: '订单管理', icon: 'el-icon-s-order', path: '/order' ,component:'Order'},
]
axios二次封装
import axios from 'axios';
const _axios = axios.create({
baseURL:'https://www.fastmock.site/mock/56fbd71662d3ff554b25859d7b965943/api'
});
// 添加请求拦截器
_axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
_axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
export default _axios;
import _axios from '@/util/request.js'
export function getNavData(){
return _axios({
method:'get',
url:'/menuList'
})
}
二、动态添加菜单
<template>
<div id="app">
<div class="layout">
<div class="leftMenu">
<el-menu
router
:default-active="$route.path"
>
<el-menu-item
v-for="(item,index) in lists"
:index="item.path"
:key="index"
>
<i :class="item.icon"></i>
<span slot="title">{{item.tilte}}</span>
</el-menu-item>
</el-menu>
</div>
<div class="rightContent">
<router-view></router-view>
</div>
</div>
</div>
</template>
<script>
import { getNavData } from '@/api/index'
export default {
name: 'app',
components: {
},
mounted() {
console.log(this.$route.path)
},
data() {
return {
lists: []
}
},
mounted() {
this.getMenuList();
},
methods: {
getMenuList() {
getNavData().then(res => {
console.log(res);
let { code, menuList } = res.data
if (code == 200) {
this.lists = menuList;
}
}).catch(err => {
})
}
}
}
</script>
<style lang="scss">
* {
padding: 0;
margin: 0;
}
html,
body,
#app {
width: 100vw;
height: 100vh;
}
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
.layout {
width: 100vw;
height: 100vh;
display: flex;
.leftMenu {
flex-basis: 200px;
}
.rightContent {
flex: 1;
background: wheat;
}
}
}
</style>
三、动态添加路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import { getNavData } from '@/api/index'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'HomePage',
redirect:'/home',
component: Home
}
]
const router = new VueRouter({
linkActiveClass:'selected',
routes
})
// 路由拦截,在url地址跳转之前执行
router.beforeEach((to,from,next)=>{
addRoutes();
next()
})
function addRoutes(){
getNavData().then(res=>{
console.log(res);
let { code, menuList } = res.data;
if(code ==200){
// 拼接路由数据
let data = routesData(menuList);
router.addRoutes(data);
}
})
}
function routesData(menuList){
menuList.forEach(item=>{
routes.push({
path:item.path,
name:item.name,
meta:{title:item.title},
component:()=>import(`../views/content/${item.component}`)
})
})
return routes;
}
export default router
四、数据缓存
使用vuex减少请求次数
配置vuex方法
mport Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
nav:[]
},
mutations: {
setNav(state,nav){
state.nav = nav
}
},
actions: {
SET_NAV({commit},nav){
commit('setnav',nav);
}
},
modules: {
}
})
五、菜单从vuex获取数据
<template>
<div id="app">
<div class="layout">
<div class="leftMenu">
<el-menu
router
:default-active="$route.path"
>
<el-menu-item
v-for="(item,index) in nav"
:index="item.path"
:key="index"
>
<i :class="item.icon"></i>
<span slot="title">{{item.tilte}}</span>
</el-menu-item>
</el-menu>
</div>
<div class="rightContent">
<router-view></router-view>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
name: 'app',
components: {
},
mounted() {
console.log(this.$route.path)
},
data() {
return {
lists: []
}
},
computed: mapState([
'nav'
])
}
</script>
<style lang="scss">
* {
padding: 0;
margin: 0;
}
html,
body,
#app {
width: 100vw;
height: 100vh;
}
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
.layout {
width: 100vw;
height: 100vh;
display: flex;
.leftMenu {
flex-basis: 200px;
}
.rightContent {
flex: 1;
background: wheat;
}
}
}
</style>
六、在router里加入vuex的存储逻辑
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import store from '@/store'
import { getNavData } from '@/api/index'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'HomePage',
redirect:'/home',
component: Home
}
]
const router = new VueRouter({
linkActiveClass:'selected',
routes
})
// 路由拦截,在url地址跳转之前执行
router.beforeEach((to,from,next)=>{
addRoutes();
next()
})
function addRoutes(){
if(store&&store.state.nav.length == 0 ){
getNavData().then(res=>{
console.log(res);
let { code, menuList } = res.data;
if(code ==200){
// 拼接路由数据
store.dispatch('SET_NAV',menuList)
let data = routesData(menuList);
// 动态路由 addRoutes
router.addRoutes(data);
}
})
}
}
function routesData(menuList){
menuList.forEach(item=>{
routes.push({
path:item.path,
name:item.name,
meta:{title:item.title},
component:()=>import(`../views/content/${item.component}`)
})
})
return routes;
}
export default router