之前做过一期菜单,但感觉做的不好,所以这里在补一期较为完善的。
话不多说,先上效果图,对于系统菜单来说,无非就是多级渲染,再加一点小功能

1.在components文件夹下建立test.vue页面,
<template>
<fragment class="navMenu">
<template v-for="navMenu in navMenus">
<el-menu-item v-if="!navMenu.children&&navMenu.Info"
:key="navMenu.Info.Id" :data="navMenu" :index="navMenu.Info.Id"
:route="navMenu.Info.url +'/'+ navMenu.Info.Id"
>
<i :class="navMenu.Info.PicName"></i>
<span slot="title">{{navMenu.Info.label}}</span>
</el-menu-item>
<el-submenu v-if="navMenu.children&&navMenu.Info"
:key="navMenu.Info.Id" :data="navMenu" :index="navMenu.Info.Id">
<template slot="title">
<i :class="navMenu.Info.PicName"></i>
<span> {{navMenu.Info.label}}</span>
</template>
<NavMenu :navMenus="navMenu.children"></NavMenu>
</el-submenu>
</template>
</fragment>
</template>
<script>
export default {
name: 'NavMenu',
props: ['navMenus'],
data() {
return {
}
},
created(){
},
methods: {
}
}
</script>
<style>
</style>
npm install --save vue-fragment
然后到main里面注入
import Fragment from ‘vue-fragment’
Vue.use(Fragment.Plugin)
2.至此组件已经弄完了,现在我们来看调用
<!-- 菜单栏 -->
<div class="dis">
<div class="Mnum_box" :style="isCollapse ? ' width: 64px;' : 'width: 200px;'">
<el-menu
:unique-opened = true
background-color='#212c3c'
text-color='#fff'
class="el-menu-vertical-demo"
@open="handleOpen"
router
:default-active='curActive'
@select="handleselect"
active-text-color="#418de9"
@close="handleClose"
:collapse="isCollapse"
>
<NavMenu :navMenus="menuData"></NavMenu>
</el-menu>
</div>
<!-- 菜单栏 -->
<!-- 顶部历史条 及子路由显示-->
<div class="ChildRouter" :style="isCollapse ? 'margin-left: 64px; width: calc(100% - 64px);' : 'margin-left: 200px; width: calc(100% - 200px);'">
<router-view></router-view>
</div>
<!-- 顶部历史条-->
</div>
上面是Html内容 =======================
isCollapse: false, //折叠菜单
menuData: [],//菜单列表
curActive:null,//默认打开的菜单key
上面是需要用到的数据 =========================
handleOpen(key, keyPath) { //菜单打开
},
handleClose(key, keyPath) { //菜单关闭
},
handleselect(key, keyPath){ //菜单点击
sessionStorage.setItem("RouID", key);
},
上面是需要用到的函数 =========================
.Mnum_box{
overflow: scroll;
width: 200px;
color: #a2adc1;
background-color: #212c3c;
border: 0;
height: 100%;
position: absolute;
margin-bottom: 50px;
}
.Mnum_box::-webkit-scrollbar {/*滚动条整体样式*/
width: 5px; /*高宽分别对应横竖滚动条的尺寸*/
height: 1px;
}
.Mnum_box::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
border-radius: 10px;
-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
background: #535353;
}
.Mnum_box::-webkit-scrollbar-track {/*滚动条里面轨道*/
-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
border-radius: 10px;
background: #f1f4f5;
}
上面是需要用到的美化菜单样式 =========================
值得一提的是菜单用到的menuData数据结构 :
[{
"Info": {
"num": "1",
"Id": "1",
"label": "控制台管理",
"PicName": "el-icon-menu",
"PicUrl": null,
"url": "",
"remark": null
},
"children": [{
"Info": {
"num": null,
"Id": "55",
"label": "控制台",
"PicName": "",
"PicUrl": null,
"url": "/Home/indexCorp",
"remark": null
},
"children": null
}]
}, {
"Info": {
"num": "2",
"Id": "2",
"label": "项目管理",
"PicName": "el-icon-s-cooperation\r\n",
"PicUrl": null,
"url": "",
"remark": null
},
"children": [{
"Info": {
"num": null,
"Id": "3",
"label": "项目列表",
"PicName": null,
"PicUrl": null,
"url": "/projectManagement/projectList",
"remark": null
},
"children": null
}]
}, {
"Info": {
"num": "3",
"Id": "4",
"label": "签约管理",
"PicName": "el-icon-s-management",
"PicUrl": null,
"url": "",
"remark": null
},
"children": [{
"Info": {
"num": null,
"Id": "56",
"label": "签约管理",
"PicName": "",
"PicUrl": null,
"url": "/employee/indexTwo",
"remark": null
},
"children": null
}]
}, {
"Info": {
"num": "4",
"Id": "5",
"label": "结算管理",
"PicName": "el-icon-coin",
"PicUrl": null,
"url": "",
"remark": null
},
"children": [{
"Info": {
"num": null,
"Id": "6",
"label": "验收结算",
"PicName": "",
"PicUrl": null,
"url": "/trade/applyList",
"remark": null
},
"children": null
}, {
"Info": {
"num": null,
"Id": "7",
"label": "明细查询",
"PicName": "",
"PicUrl": null,
"url": "/trade/tradeDetailAll",
"remark": null
},
"children": null
}]
}, {
"Info": {
"num": "5",
"Id": "8",
"label": "财务管理",
"PicName": "el-icon-s-finance",
"PicUrl": null,
"url": "",
"remark": null
},
"children": [{
"Info": {
"num": null,
"Id": "9",
"label": "我的账户",
"PicName": "",
"PicUrl": null,
"url": "/bill/rechargeCorp",
"remark": null
},
"children": null
}, {
"Info": {
"num": null,
"Id": "10",
"label": "我的账单",
"PicName": "",
"PicUrl": null,
"url": "/bill/list",
"remark": null
},
"children": null
}]
}, {
"Info": {
"num": "6",
"Id": "11",
"label": "发票管理",
"PicName": "el-icon-s-order",
"PicUrl": null,
"url": "",
"remark": null
},
"children": [{
"Info": {
"num": null,
"Id": "12",
"label": "申请发票",
"PicName": "",
"PicUrl": null,
"url": "/invoice/add",
"remark": null
},
"children": null
}, {
"Info": {
"num": null,
"Id": "13",
"label": "发票列表",
"PicName": "",
"PicUrl": null,
"url": "/invoice/list",
"remark": null
},
"children": null
}]
}, {
"Info": {
"num": "7",
"Id": "14",
"label": "系统管理",
"PicName": "el-icon-s-tools",
"PicUrl": null,
"url": "",
"remark": null
},
"children": [{
"Info": {
"num": null,
"Id": "15",
"label": "企业设置",
"PicName": "",
"PicUrl": null,
"url": "/systemManagement/setting",
"remark": null
},
"children": null
}, {
"Info": {
"num": null,
"Id": "16",
"label": "消息中心",
"PicName": "",
"PicUrl": null,
"url": "/systemManagement/notice",
"remark": null
},
"children": null
}, {
"Info": {
"num": null,
"Id": "17",
"label": "帮助中心",
"PicName": "",
"PicUrl": null,
"url": "",
"remark": null
},
"children": null
}]
}]
(url为菜单路径,id为唯一标识,label为菜单名称,PicName为elemnt ui 图标名称)
以上就是基本菜单渲染了
现在需要在刷新时,自动定位到菜单,并展开菜单
1.这里我用sessionStorage 缓存实现
handleselect(key, keyPath){ //菜单点击
sessionStorage.setItem("RouID", key);
},
这里的key就是上面数据的id属性,看个人情况 (id必须唯一)
缓存后在页面刷新时 赋值 (:default-active='curActive')
this.curActive = sessionStorage.getItem("RouID")
此时就能定位到该菜单了
当然一些特殊情况下需要用到监听路径并赋值:
watch: {
'$route' (to, from) {
this.curActive = this.$route.params.menuId
}
},
路由配置的话可以选择(看个人而言)
{ //我的账户
path: '/bill/rechargeCorp/:menuId',
name: 'RechargeCorp',
component: () => import('@/pages/components/Shop/bill/rechargeCorp')
},
最后发几张效果图:


