饿了么组件库,element-ui开发精美的后台管理系统系列之(一)开发伸缩菜单...


涉及到路由,权限等等相关内容的部分,跟本文主旨关系不大,所以我将会在另外一篇文章中详述,混在一起的话内容太多了


基于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也行。先看效果,再看代码(代码看上去有点长,别被吓着,我后面详细讲解):
这是收缩的状态:
clipboard.png

这是展开的状态:
clipboard.png

<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">&nbsp;&nbsp;&nbsp;<i :class="getIcon(item.permissionName)">&nbsp;&nbsp;&nbsp;</i>{{item.permissionName}}</template>
                            <el-menu-item v-for="child in authMenu" :index="child.uri" :key="child.permissionMark" v-if="item.permissionCode==child.parentPermissionCode">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i :class="getIcon(child.permissionName)">&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;{{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">&nbsp;&nbsp;&nbsp;<i :class="getIcon(item.permissionName)">&nbsp;&nbsp;&nbsp;</i>{{item.permissionName}}</template>
                            <el-menu-item v-for="child in authMenu" :index="child.uri" :key="child.permissionMark" v-if="item.permissionCode==child.parentPermissionCode">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i :class="getIcon(child.permissionName)">&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;{{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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值