涉及到路由,权限等等相关内容的部分,跟本文主旨关系不大,所以我将会在另外一篇文章中详述,混在一起的话内容太多了
基于element-ui的左侧可伸缩的菜单
通过vuejs来开发支持展开收缩的菜单是非常简单的,只需要v-if v-else即可简单实现,下面我分步骤详细讲解过程,并在后续的系列文章中详细讲解权限菜单、路由过滤等等一些实用的技巧。当然还包括完整实现后台管理页面所要重点关注的细节。
如何把权限菜单展示出来呢?
首先,这是一个动态菜单,该显示什么样的菜单需要从后端获取,规则方面如下:
[
{
'label': '这个菜单',
'id': 001,
'parntid': 0
},
{
'label': '那个菜单',
'id': 002,
'parntid': 0
},
{
'label': '二个菜单',
'id': 003,
'parntid': 001
},
{
'label': '三个菜单',
'id': 003,
'parntid': 001
},
{
'label': '四个菜单',
'id': 003,
'parntid': 002
},
{
'label': '吴个菜单',
'id': 003,
'parntid': 002
}
]
注意:我这里是用的两级菜单,同样的原理可以很简单的生成多级的。json中通过id来实现父子关联,也可以改成多级的json,用child来表示子级,子级的子级。这样也可以很容易的生成多级的多级菜单。不过通常也就两级或者三级。原理相同很容易扩展,如果不知道怎么扩展欢迎加入qq群:478694438来探讨。
下面看一下菜单的展示,需要aside标签,aside标签是html5的标签,没见过aside ?不要紧换成div也行。先看效果,再看代码(代码看上去有点长,别被吓着,我后面详细讲解):
这是收缩的状态:
这是展开的状态:
<aside :class="collapsed?'menu-expanded':'menu-collapsed'">
<el-menu default-active="/ManageRole" v-if="collapsed" class="el-menu-vertical-demo" router>
<template v-for="(item,index) in authMenu">
<el-submenu :index="index+''" v-if="item.parentPermissionCode==0">
<template slot="title"> <i :class="getIcon(item.permissionName)"> </i>{{item.permissionName}}</template>
<el-menu-item v-for="child in authMenu" :index="child.uri" :key="child.permissionMark" v-if="item.permissionCode==child.parentPermissionCode"> <i :class="getIcon(child.permissionName)"> </i>{{child.permissionName}}</el-menu-item>
</el-submenu>
</template>
</el-menu>
<ul class="el-menu collapsed" ref="menuCollapsed" v-else>
<li v-for="(item,index) in authMenu" v-if="item.parentPermissionCode==0" class="el-submenu item">
<template>
<div class="el-submenu__title" style="padding-left: 20px;" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)"><i :class="getIcon(item.permissionName)"></i></div>
<ul class="el-menu tipMenu" :class="'submenu-hook-'+index" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
<li v-for="child in authMenu" :key="child.uri" v-if="item.permissionCode==child.parentPermissionCode" class="el-menu-item" style="padding-left: 40px;" :class="$route.path==child.path?'is-active':''" @click="$router.push(child.uri)"><i :class="getIcon(child.permissionName)"></i> {{child.permissionName}}</li>
</ul>
</template>
</li>
</ul>
<div class="changeState" @click="collapsed=!collapsed">
<i v-if="collapsed" class="iconfont icon-zuoyou1"></i>
<i v-else class="iconfont icon-zuoyou"></i>
</div>
</aside>
来分析一下这些乱糟糟的代码(这是我从源码中截出来的所以看起来有点乱):
<el-menu>、<ul>、changeState这三个都是aside标签下的同级的标签,分别对应:展开状态下的菜单、收缩状态下的菜单、切换状态的箭头。
先看el-menu:
<el-menu default-active="/ManageRole" v-if="collapsed" class="el-menu-vertical-demo" router>
<template v-for="(item,index) in authMenu">
<el-submenu :index="index+''" v-if="item.parentPermissionCode==0">
<template slot="title"> <i :class="getIcon(item.permissionName)"> </i>{{item.permissionName}}</template>
<el-menu-item v-for="child in authMenu" :index="child.uri" :key="child.permissionMark" v-if="item.permissionCode==child.parentPermissionCode"> <i :class="getIcon(child.permissionName)"> </i>{{child.permissionName}}</el-menu-item>
</el-submenu>
</template>
</el-menu>
collapsed这个值即为判断显示展开还是收缩状态的开关。对照ul下的v-else看。通过一个v-for 循环除所有的父级菜单,再次循环寻找子级菜单中parentId==id的子菜单,作为该父级菜单下的子菜单。这样就实现了展开状态下的菜单。
注意:图标的问题,图标可以选择从后端返回class,这样做起来起来更简单,我这里是通过预设一个getIcon()函数在本地设置显示,由于图标和路由面临的是相同的实现,所以我会在路由跳转相关的地方详细解释一下,应该在何种场景下选择何种方式。
再看ul:
<ul class="el-menu collapsed" ref="menuCollapsed" v-else>
<li v-for="(item,index) in authMenu" v-if="item.parentPermissionCode==0" class="el-submenu item">
<template>
<div class="el-submenu__title" style="padding-left: 20px;" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)"><i :class="getIcon(item.permissionName)"></i></div>
<ul class="el-menu tipMenu" :class="'submenu-hook-'+index" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
<li v-for="child in authMenu" :key="child.uri" v-if="item.permissionCode==child.parentPermissionCode" class="el-menu-item" style="padding-left: 40px;" :class="$route.path==child.path?'is-active':''" @click="$router.push(child.uri)"><i :class="getIcon(child.permissionName)"></i> {{child.permissionName}}</li>
</ul>
</template>
</li>
</ul>
这根element-ui就没有关系了,简单的ul li 实现。(路由相关的可以展示忽略,我会在下一篇文章中详细描述)
最后看:
<div class="changeState" @click="collapsed=!collapsed">
<i v-if="collapsed" class="iconfont icon-zuoyou1"></i>
<i v-else class="iconfont icon-zuoyou"></i>
</div>
通过collapsed 在v-if v-else中绑定视图简单实现了,开关功能。
写在最后
这个功能看似简单却包含了vuejs的十几个知识点。难倒了很多人,我之所有写这篇文章,也是因为很多朋友,在此之前不断的询问我如何才能优雅的实现这个功能。当然了这只一个完整的后台管理的开始,我将会在后面的文章中继续讲解关于大家最关心的要不要使用addRoutes,如何使用addRoutes,不使用addRoutes的情况下如何使用路由拦截来有没的实现路由与权限的匹配,包括系统内部不同权限展示不同的操作界面的问题,当然了这是后话。如果有时间的话,我会把这个系列写完,知道朋友们能独立开发一个完整的vuejs的单页面后台管理程序。
另
文中设计的代码我将会上传到讨论群中(478694438),不足之处优化共同探讨。
所有评论(0)