在我们做管理后台亦或是产品流程时,总是需要一个菜单栏或者导航栏来架起我们的产品架构,那么,如何用vue实现侧边折叠导航栏呢?接下来将一一介绍。
请先看效果演示图。
步骤1:先架构整个页面的布局,撰写html、css和js
HTML代码
<template><div id="main"><div class="content"><!-- 左边导航栏 --><div class="admin_nav col-lg-3 col-xl-2" v-show="fullWidth"><div class = "admin_nav_site"><div class="title">数据中心后台管理</div><ul v-for="(item,index) in navList" :key="index"><li @click="handleToTitle(index,item)" @mouseenter="changeTitleColor(index)" @mouseleave="removeTitleColor(index)"ref="title" :class="{active:currentSort == index}" class="col-lg-12"><div class="left_icon"><i :class="'iconfont '+item.className"></i></div><div class="middle">{{item.title}}</div><div class="right_icon"><i :class="'iconfont '+item.close"></i></div></li><li v-for="(it,idx) in item.secMenu" :key="idx" v-show="item.isSubShow" class="active1"><router-link :to="it.path" tag="a">{{it.name}}</router-link></li></ul></div></div><!-- 右边内容 --><div class="admin_content col-12 col-md-12 col-lg-12 col-xl-10"><div class="admin_header"><!-- 导航图标 --><div class="H5_item" v-show="!fullWidth"><i class="iconfont icon-daohanglan" @click="make_menu" class-name="H5-menu"></i></div><div class="user"><div class="userHead"><span><img src="../../assets/image/userhead.svg"></span><span>admin</span></div><div class="logOut"><i class="iconfont icon-tuichu"></i></div></div></div><div class="admin_body"><keep-alive><router-view /></keep-alive></div></div></div></div>
</template>
JS代码
<script>import axios from 'axios';export default {name: 'navigation',data() {return {navList: [{title: '用户管理',isSubShow: false,className: 'icon-guanliyuan1',close: 'icon-close',up: 'icon-zhedie',secMenu: [{name: '工号管理',path: '/home/navigation-one/user'}, // {// name: '角色管理',// path: '/home/navigation-one/role'// }, // {// name: '权限管理',// path: '/home/navigation-one/user'// }, ]},{title: '资源管理',isSubShow: false,className: 'icon-ziyuan',close: 'icon-close',up: 'icon-zhedie',secMenu: [{name: '我的收藏',path: '/home/navigation-one/user'},{name: '我的项目',path: '/home/navigation-one/role'}]},{title: '综合管理',isSubShow: false,className: 'icon-zonghe',close: 'icon-close',up: 'icon-zhedie',secMenu: [{name: '划配管理',path: '/home/navigation-one/user'},{name: '数据信息',path: '/home/navigation-one/role'}]},{title: '系统消息',isSubShow: false,className: 'icon-xiaoxi',close: 'icon-close',up: 'icon-zhedie',secMenu: [{name: '实时动态',path: '/home/navigation-one/user'},{name: '过去动态',path: '/home/navigation-one/role'}]}],currentSort: 0,pagetype: "index",fullWidth: true,dismenu: true}},methods: {active(index) {this.currentSort = index;},changeTitleColor(index) {this.currentSort = index;},removeTitleColor(index) {this.currentSort = null;},handleToTitle(ind, item) {this.navList[ind].isSubShow = !this.navList[ind].isSubShow;if (this.navList[ind].isSubShow == true) {this.navList[ind].close = 'icon-zhedie';} else {this.navList[ind].close = 'icon-close';}}}}
</script>
CSS代码
#main {background: #F0F6FF;font-size: 0.16rem;}#main .content {display: flex;flex-direction: row;}.content .admin_nav {min-height: 9.37rem;max-height: 1.3rem;padding: 0 !important;background: #364150;position: relative;}.content .admin_nav .admin_nav_site{height: 100vh;}.content .admin_nav .title {height: 1.39rem;line-height: 1.39rem;background: rgba(63, 73, 86, 1);color: #FFFFFF;text-align: center;font-size: 0.18rem;display: flex;justify-content: center;}.content .admin_nav .title div {padding: 0 0.03rem;}.content .admin_nav .title div:first-child i {font-size: 0.18rem;}.content .admin_nav ul .active {background: rgba(68, 81, 99, 1);}.content .admin_nav ul .active1 a.router-link-active {color: #fff;}.content .admin_nav ul li {height: 0.6rem;display: flex;flex-direction: column;justify-content: center;align-items: center;font-size: 0.18rem;}.content .admin_nav ul li a {color: #cecdc5;cursor: pointer;}.content .admin_nav ul li:first-child {font-size: 0.2rem;height: 0.64rem;display: flex;flex-direction: row;align-items: center;color: #BEC5C0;cursor: pointer;}.content .admin_nav ul li:first-child div {width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;color: #BEC5C0;}.content .admin_nav ul li:first-child .left_icon {width: 22%;}.content .admin_nav ul li:first-child .left_icon i {color: #1296DB;}.content .admin_nav ul li:first-child .middle {width: 56%;display: flex;justify-content: flex-start;}.content .admin_nav ul li:first-child .right_icon {width: 22%;}.admin_nav .admin .middle:hover {color: #fff;}.admin_nav .admin .right_icon i:hover {color: #fff;}.admin_nav .admin .middle.router-link-active {color: #fff;}.content .admin_nav_position {position: absolute;z-index: 3000;}.content .admin_content {padding: 0 !important;}.content .admin_content .admin_header {width: 100%;height: 0.6rem;background: #364150;display: flex;flex-direction: row;align-items: center;justify-content: space-between;}.content .admin_content .admin_header .H5_item {width: 0.4rem;height: 0.4rem;border-radius: 0.2rem;display: flex;justify-content: center;align-items: center;margin-left: 0.2rem;}.content .admin_content .admin_header .H5_item i {font-size: 0.22rem;color: #fff;}.content .admin_content .admin_header .user {width: 100%;display: flex;align-items: center;justify-content: flex-end;}.content .admin_content .admin_header .user .userHead {height: 0.6rem;display: flex;flex-direction: row;align-items: center;color: #fff;font-size: 0.18rem;}.content .admin_content .admin_header .user .userHead span {padding: 0 0.05rem;}.content .admin_content .admin_header .user .userHead span:nth-child(1) {position: relative;}.content .admin_content .admin_header .user .userHead span img {width: 0.4rem;height: 0.4rem;border-radius: 50%;}.content .admin_content .admin_header .user .userHead span input {width: 0.4rem;height: 0.4rem;position: absolute;overflow: hidden;opacity: 0;cursor: pointer;}.content .admin_content .admin_header .user .logOut {color: #fff;margin-left: 0.12rem;margin-right: 0.5rem;}.content .admin_content .admin_header .user .logOut i {color: #1296DB;font-size: 0.24rem;cursor: pointer;}.toggle-cart-enter-active {transition: all 0.4s linear;}.toggle-cart-leave-active {transition: all 0.4s linear;}.toggle-cart-enter {transform: translateX(-200%);}.toggle-cart-leave-active {transform: translateX(-200%);}
步骤2:撰写完基本网页布局和样式后,对部分细节进行剖析。
1、动态绑定路径
<router-link :to="it.path" tag="a">{{it.name}}</router-link>
2、一级菜单,标题及折叠符号
①通过@mouseenter和@mouseleave事件,当鼠标移入和移出时,改变标题区域背景颜色
②通过@click事件,当鼠标点击时,显示二级菜单列表
③利用:class动态绑定类名,触发active方法,修改折叠符号状态;绑定图标类名,通过遍历,修改对应图标
<ul v-for="(item,index) in navList" :key="index"><li @click="handleToTitle(index,item)" @mouseenter="changeTitleColor(index)" @mouseleave="removeTitleColor(index)" ref="title" :class="{active:currentSort == index}" class="col-lg-12"><div class="left_icon"><i :class="'iconfont '+item.className"></i></div><div class="middle">{{item.title}}</div><div class="right_icon"><i :class="'iconfont '+item.close"></i></div></li><li v-for="(it,idx) in item.secMenu" :key="idx" v-show="item.isSubShow" class="active1"><router-link :to="it.path" tag="a">{{it.name}}</router-link></li>
</ul>
active(index) {this.currentSort = index;
},changeTitleColor(index) {this.currentSort = index;
},removeTitleColor(index) {this.currentSort = null;
},handleToTitle(ind, item) {this.navList[ind].isSubShow = !this.navList[ind].isSubShow;if (this.navList[ind].isSubShow == true) {this.navList[ind].close = 'icon-zhedie';} else {this.navList[ind].close = 'icon-close';}
}
步骤3:菜单栏完成后,在网页端能进行查看,但是还需做一个手机端适配,这样就达到两端同步适应的效果。实现如下:
①对左边导航栏再撰写第二套代码,并绑定好对应的参数实现显示和隐藏
②运用vue已有的transition,绑定name值,实现动画效果绑定
HTML代码
<!-- 移动端导航栏 -->
<transition name="toggle-cart"><div class="admin_nav admin_nav_position col-8 col-md-5 col-lg-3 col-xl-3" v-show="!fullWidth&&!dismenu"><div class="title"><div v-show="!fullWidth"><i class="iconfont icon-daohanglan" @click="make_menu" class-name="H5-menu"></i></div><div>数据中心后台管理</div></div><ul v-for="(item,index) in navList" :key="index"><li @click="handleToTitle(index,item)" @mouseenter="changeTitleColor(index)" @mouseleave="removeTitleColor(index)" ref="title" :class="{active:currentSort == index}"><div class="left_icon"><i :class="'iconfont '+item.className"></i></div><div class="middle">{{item.title}}</div><div class="right_icon"><i :class="'iconfont '+item.close"></i></div></li><li v-for="(it,idx) in item.secMenu" :key="idx" v-show="item.isSubShow" class="active1"><router-link :to="it.path" tag="a">{{it.name}}</router-link></li></ul></div>
</transition>
JS代码
mounted() {window.onresize = () => { //监听屏幕变化this.page_width();};this.page_width();
},
methods: {make_menu() { //点击导航图标this.dismenu = !this.dismenu;},page_width() { //获取屏幕宽度var screenWidth = window.screen.width;if (screenWidth <= 1024) {this.fullWidth = false;} else {this.fullWidth = true;}}
}
最后来看下手机端效果:
附上全文代码:
<template><div id="main"><div class="content"><!-- 左边导航栏 --><div class="admin_nav col-lg-3 col-xl-2" v-show="fullWidth"><div class = "admin_nav_site"><div class="title">数据中心后台管理</div><ul v-for="(item,index) in navList" :key="index"><li @click="handleToTitle(index,item)" @mouseenter="changeTitleColor(index)" @mouseleave="removeTitleColor(index)" ref="title" :class="{active:currentSort == index}" class="col-lg-12"><div class="left_icon"><i :class="'iconfont '+item.className"></i></div><div class="middle">{{item.title}}</div><div class="right_icon"><i :class="'iconfont '+item.close"></i></div></li><li v-for="(it,idx) in item.secMenu" :key="idx" v-show="item.isSubShow" class="active1"><router-link :to="it.path" tag="a">{{it.name}}</router-link></li></ul></div><!-- 管理员端 --><!-- <ul class="admin"><li class="col-lg-12"><div class="left_icon"><i class="iconfont icon-guanliyuan1"></i></div><router-link to="/admin/administrator/secadmin" tag="div" class="middle">管理员端</router-link><div class="right_icon"><i class="iconfont icon-jinru"></i></div></li></ul> --></div><!-- 右边内容 --><div class="admin_content col-12 col-md-12 col-lg-12 col-xl-10"><div class="admin_header"><!-- 导航图标 --><div class="H5_item" v-show="!fullWidth"><i class="iconfont icon-daohanglan" @click="make_menu" class-name="H5-menu"></i></div><div class="user"><div class="userHead"><span><img src="../../assets/image/userhead.svg"></span><span>admin</span></div><div class="logOut"><i class="iconfont icon-tuichu"></i></div></div></div><div class="admin_body"><keep-alive><router-view /></keep-alive></div></div><!-- 移动端导航栏 --><transition name="toggle-cart"><div class="admin_nav admin_nav_position col-8 col-md-5 col-lg-3 col-xl-3" v-show="!fullWidth&&!dismenu"><div class="title"><div v-show="!fullWidth"><i class="iconfont icon-daohanglan" @click="make_menu" class-name="H5-menu"></i></div><div>数据中心后台管理</div></div><ul v-for="(item,index) in navList" :key="index"><li @click="handleToTitle(index,item)" @mouseenter="changeTitleColor(index)" @mouseleave="removeTitleColor(index)"ref="title" :class="{active:currentSort == index}"><div class="left_icon"><i :class="'iconfont '+item.className"></i></div><div class="middle">{{item.title}}</div><div class="right_icon"><i :class="'iconfont '+item.close"></i></div></li><li v-for="(it,idx) in item.secMenu" :key="idx" v-show="item.isSubShow" class="active1"><router-link :to="it.path" tag="a">{{it.name}}</router-link></li></ul></div></transition></div></div>
</template><script>import axios from 'axios';export default {name: 'navigation-1',data() {return {token: '',navList: [{title: '用户管理',isSubShow: false,className: 'icon-guanliyuan1',close: 'icon-close',up: 'icon-zhedie',secMenu: [{name: '工号管理',path: '/home/navigation-one/user'}, // {// name: '角色管理',// path: '/home/navigation-one/role'// }, // {// name: '权限管理',// path: '/home/navigation-one/user'// }, ]},{title: '资源管理',isSubShow: false,className: 'icon-ziyuan',close: 'icon-close',up: 'icon-zhedie',secMenu: [{name: '我的收藏',path: '/home/navigation-one/user'},{name: '我的项目',path: '/home/navigation-one/role'}]},{title: '综合管理',isSubShow: false,className: 'icon-zonghe',close: 'icon-close',up: 'icon-zhedie',secMenu: [{name: '划配管理',path: '/home/navigation-one/user'},{name: '数据信息',path: '/home/navigation-one/role'}]},{title: '系统消息',isSubShow: false,className: 'icon-xiaoxi',close: 'icon-close',up: 'icon-zhedie',secMenu: [{name: '实时动态',path: '/home/navigation-one/user'},{name: '过去动态',path: '/home/navigation-one/role'}]}],currentSort: 0,pagetype: "index",fullWidth: true,dismenu: true}},mounted() {window.onresize = () => { //监听屏幕变化this.page_width();};this.page_width();},methods: {active(index) {this.currentSort = index;},changeTitleColor(index) {this.currentSort = index;},removeTitleColor(index) {this.currentSort = null;},handleToTitle(ind, item) {this.navList[ind].isSubShow = !this.navList[ind].isSubShow;if (this.navList[ind].isSubShow == true) {this.navList[ind].close = 'icon-zhedie';} else {this.navList[ind].close = 'icon-close';}},make_menu() { //点击导航图标this.dismenu = !this.dismenu;},page_width() { //获取屏幕宽度var screenWidth = window.screen.width;if (screenWidth <= 1024) {this.fullWidth = false;} else {this.fullWidth = true;}}}}
</script><style scoped>#main {background: #F0F6FF;font-size: 0.16rem;}#main .content {display: flex;flex-direction: row;}.content .admin_nav {min-height: 9.37rem;max-height: 1.3rem;padding: 0 !important;background: #364150;position: relative;}.content .admin_nav .admin_nav_site{height: 100vh;}.content .admin_nav .title {height: 1.39rem;line-height: 1.39rem;background: rgba(63, 73, 86, 1);color: #FFFFFF;text-align: center;font-size: 0.18rem;display: flex;justify-content: center;}.content .admin_nav .title div {padding: 0 0.03rem;}.content .admin_nav .title div:first-child i {font-size: 0.18rem;}.content .admin_nav ul .active {background: rgba(68, 81, 99, 1);}.content .admin_nav ul .active1 a.router-link-active {color: #fff;}.content .admin_nav ul li {height: 0.6rem;display: flex;flex-direction: column;justify-content: center;align-items: center;font-size: 0.18rem;}.content .admin_nav ul li a {color: #cecdc5;cursor: pointer;}.content .admin_nav ul li:first-child {font-size: 0.2rem;height: 0.64rem;display: flex;flex-direction: row;align-items: center;color: #BEC5C0;cursor: pointer;}.content .admin_nav ul li:first-child div {width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;color: #BEC5C0;}.content .admin_nav ul li:first-child .left_icon {width: 22%;}.content .admin_nav ul li:first-child .left_icon i {color: #1296DB;}.content .admin_nav ul li:first-child .middle {width: 56%;display: flex;justify-content: flex-start;}.content .admin_nav ul li:first-child .right_icon {width: 22%;}.admin_nav .admin .middle:hover {color: #fff;}.admin_nav .admin .right_icon i:hover {color: #fff;}.admin_nav .admin .middle.router-link-active {color: #fff;}.content .admin_nav_position {position: absolute;z-index: 3000;}.content .admin_content {padding: 0 !important;}.content .admin_content .admin_header {width: 100%;height: 0.6rem;background: #364150;display: flex;flex-direction: row;align-items: center;justify-content: space-between;}.content .admin_content .admin_header .H5_item {width: 0.4rem;height: 0.4rem;border-radius: 0.2rem;display: flex;justify-content: center;align-items: center;margin-left: 0.2rem;}.content .admin_content .admin_header .H5_item i {font-size: 0.22rem;color: #fff;}.content .admin_content .admin_header .user {width: 100%;display: flex;align-items: center;justify-content: flex-end;}.content .admin_content .admin_header .user .userHead {height: 0.6rem;display: flex;flex-direction: row;align-items: center;color: #fff;font-size: 0.18rem;}.content .admin_content .admin_header .user .userHead span {padding: 0 0.05rem;}.content .admin_content .admin_header .user .userHead span:nth-child(1) {position: relative;}.content .admin_content .admin_header .user .userHead span img {width: 0.4rem;height: 0.4rem;border-radius: 50%;}.content .admin_content .admin_header .user .userHead span input {width: 0.4rem;height: 0.4rem;position: absolute;overflow: hidden;opacity: 0;cursor: pointer;}.content .admin_content .admin_header .user .logOut {color: #fff;margin-left: 0.12rem;margin-right: 0.5rem;}.content .admin_content .admin_header .user .logOut i {color: #1296DB;font-size: 0.24rem;cursor: pointer;}.toggle-cart-enter-active {transition: all 0.4s linear;}.toggle-cart-leave-active {transition: all 0.4s linear;}.toggle-cart-enter {transform: translateX(-200%);}.toggle-cart-leave-active {transform: translateX(-200%);}
</style>
注:
1、css样式中的rem换算成px为对应的rem值*100,如:font-size:0.24rem;=> font-size:24px;
2、文章中涉及到的iconfont类名是因为引用了阿里图标,如遇到不知道如何引用的可以翻阅博文→ https://blog.csdn.net/weixin_44803753/article/details/113423633
3、关于router-link对应的跳转,如有小伙伴不太清楚如何使用vue-router配置路由的可以翻阅博文→https://blog.csdn.net/weixin_44803753/article/details/113436625
Ending(〃'▽'〃)!