参考:
https://www.jianshu.com/p/0ceef28f99f2
实现效果:


实现步骤:
1、vuex中menu.js
minLeftMenuWidth: 35, // 折叠时左侧菜单的宽度
maxLeftMenuWidth: 180, // 展开时左侧菜单的宽度
const types = { HANDLE_LEFT_MENU: 'HANDLE_LEFT_MENU', // 收缩左侧菜单 INIT_LEFT_MENU: 'INIT_LEFT_MENU', // 初始化左侧菜单 SET_LEFT_COLLAPSE: 'SET_LEFT_COLLAPSE', // 改变左边菜单的收缩宽度 SET_FOOTER_SHOW: 'SET_FOOTER_SHOW' // 显示隐藏底部Layout }; const menu = { state: { minLeftMenuWidth: 35, maxLeftMenuWidth: 180, sidebar: { opened: true, 180 }, isCollapse: false, // 菜单默认展开 isFooter: false }, getters: { sidebar: state => state.sidebar, isCollapse: state => state.isCollapse, isFooter: state => state.isFooter }, mutations: { // 收缩菜单 [types.HANDLE_LEFT_MENU](state) { if (state.sidebar.opened) { // true state.sidebar.width = state.minLeftMenuWidth; } else { state.sidebar.width = state.maxLeftMenuWidth; } state.sidebar.opened = !state.sidebar.opened; }, // 初始化左侧菜单 [types.INIT_LEFT_MENU](state) { // eslint-disable-next-line no-self-assign state.sidebar = state.sidebar; }, // 改变左侧菜单的收缩宽度 [types.SET_LEFT_COLLAPSE](state) { state.isCollapse = !state.isCollapse; }, [types.SET_FOOTER_SHOW](state) { state.isFooter = true; } }, actions: { handleLeftMenu: ({ commit }) => { commit(types.HANDLE_LEFT_MENU); }, initLeftMenu: ({ commit }) => { commit(types.INIT_LEFT_MENU); }, setLeftCollapse: ({ commit }) => { commit(types.SET_LEFT_COLLAPSE); } } }; export default menu;
2、leftMenu.vue
DOM部分:
<template> <div class="left_menu" :style="{ sidebar.width + 'px' }"> // 根据菜单是否折叠整体设计左侧菜单的宽度 <div class="menu_page_top"> <img :src="logo" :class="['logo', { closeLogo: !sidebar.opened }]" /> // 根据左侧菜单是否展开设置折叠时logo的样式:closeLogo <!-- <span class="title"> AI. <i>ADMIN</i> </span> --> </div> <div class="menu_page_bottom"> <el-menu :default-active="activeIndex" :show-timeout="200" :active-text-color="menuObj.activeTextColor" :text-color="menuObj.textColor" router :collapse="isCollapse" :style="{ sidebar.width + 'px' }" > <!-- 只有一级菜单 --> <template v-for="item in permission_routers"> <el-menu-item :index="item.path" :key="item.path" v-if="!item.hidden && item.noDropDown" :to="item.path + '/' + item.children[0].path" > <i class="iconfont icon" :class="item.meta.icon"></i> <span slot="title">{{ $t(`commons.${item.name}`) }}</span> </el-menu-item> <!-- 有二级或多级菜单 --> <el-submenu v-if=" item.children && item.children.length >= 1 && !item.hidden && !item.noDropDown " :index="item.path" :key="item.path" class="erji_menu" > <template slot="title"> <i class="iconfont icon" :class="item.meta.icon"></i> <span slot="title" v-if="item.meta.title">{{ $t(`commons.${item.name}`) }}</span> </template> <el-menu-item :index="item.path + '/' + item2.path" v-for="item2 in item.children" :key="item2.path" >{{ $t(`commons.${item2.name}`) }}</el-menu-item > </el-submenu> </template> </el-menu> </div> </div> </template>
Script部分:
<script> import { mapGetters } from 'vuex'; import * as mUtils from '@/utils/mUtils'; import logoImg from '@/assets/img/logo.png'; export default { data() { return { logo: logoImg, menuObj: { bgColor: '#fff', textColor: '#666', activeTextColor: '#ff6428' } }; }, computed: { // permission_routers:不需要权限的页面 ...mapGetters(['permission_routers', 'isCollapse', 'sidebar', 'menuIndex']), activeIndex() { return this.$route.path; }, childRouters() { return this.permission_routers.filter(item => { return ( item.children && item.children.length >= 1 && !item.hidden && !item.noDropDown ); }); } }, methods: { getIindex(citem, item, cindex) { return citem.meta.titleList ? item.path + '/' + citem.path + '/' + citem.meta.titleList[0].path : item.path + '/' + citem.path; } } }; </script>
点击右边的“折叠”与“展开”图标,实现左侧菜单的折叠与展开:
<template>
<div class="bread">
<span class="iconfont icon icon-zhedie1" @click="hanleLeftMenu"></span>
<el-breadcrumb separator="/">
<el-breadcrumb-item v-for="(item, index) in matchedArr" :key="index">{{
$t(`commons.${item}`)
}}</el-breadcrumb-item>
</el-breadcrumb>
</div>
</template>
<script>
export default {
computed: {
matchedArr() {
const temp = [];
const temps = [];
// $route.matched: 一个数组,包含当前路由的所有嵌套路径片段的路由记录 。路由记录就是 routes 配置数组中的对象副本 (还有在 children 数组)。
this.$route.matched.filter(item => {
if (item.name) {
const name = item.name;
temp.push(name);
}
});
console.log(temp);
temp.filter(item => {
if (!temps.includes(item)) {
temps.push(item);
}
});
return temps;
// return this.$route.matched;
}
},
methods: {
hanleLeftMenu() {
this.$store.dispatch('setLeftCollapse'); // 折叠菜单
this.$store.dispatch('handleLeftMenu'); // 改变宽度
}
}
};
</script>
<style lang="less" scoped>
.bread {
margin-top: 60px;
display: flex;
justify-content: flex-start;
padding: 10px;
.icon {
vertical-align: middle;
margin-right: 10px;
}
// .el-breadcrumb {
// line-height: 30px;
// }
}
</style>