上篇文章(webpack+vue项目实战(一,搭建运行环境和相关配置))搭建了好了基本的一个项目目录,安好好了一些要用到的依赖,以及把项目跑了起来。接下来,咱们就进行第二步的操做,第二步就是作好一个开发系统的主页面,这个页面主要也就是一个侧边栏,经过侧边栏的各个选项来进行操做(切换各个组件)。好比回款管理,订单管理,物流管理等等的操做。javascript
开始属于排版这一块了,是时候在index.js引入一个公用样式了,至关于一个样式重置表。css
需求有一个,页面上面须要放一个退出的登陆按钮,我就写了一个顶部组件的文件。首先就是建立这个文件html
代码以下vue
<template> <div class="topbar"> <el-button class="fr mr30 mt15" type="primary" size="small" @click="loginOut">退出登陆</el-button> </div> </template> <script> export default{ data(){ return { name: 'topbar' } }, methods: { loginOut(){ ... } }, mounted(){ } } </script> <style lang="scss" scoped> .topbar { width: 100%; height: 60px; } </style>
而后入口文件(index.js
)引用这个文件,而且在vue中注册组件import topbarComponent from './../components/admin_base/topbar.vue';
java
而后入口模板文件,index.html引入标签
页面结果(基于上一篇文章,已经跑起来的结果)webpack
页面上的class在公用样式里面有写好样式,还有一些样式是element-ui提供的,
<el-button>退出登陆</el-button>
就是element-ui提供的组件,在入口文件index.js已经引入了element-ui。这里直接用就好!web
这个比较简单,我就很少说了。vue-router
这个侧边栏就是这篇文章的重点,也是整个项目操做的重点。先在目录上建立这样一个的侧边栏的组件文件。element-ui
下面图片是咱们要实现的效果,那些排版切图的样式我很少说了,相信不会难倒你们segmentfault
从上面的效果图的看到。有3个菜单(首页,销售消息通知,销售管理)。并且首页这个菜单能够点击,执行跳转,其它两个菜单又有子菜单,点击只是一个子菜单显示与隐藏的操做。
因此,侧边栏的数据确定是一个数组,而且是一个对象数组。每一个对象至少有四个属性(要显示的文字,跳转的url,是否有子菜单,是否当前菜单)。而后对于有子菜单的菜单,要给一个属性控制是否展开显示子菜单,要一个属性,储存子菜单。
以下面文字
[ { 菜单名:'菜单名称(首页)', 跳转的url:'url(/index)', 是否当前标识:'一个标志string(0)', 是否有子菜单:'是否 true||false' }, { 菜单名:'菜单名称(首页)', 跳转的url:'url(/index)', 是否当前标识:'一个标志string(0)', 是否有子菜单:'true||false', 是否展现:'是否 true||false', 子菜单:[] } ]
对于子菜单,因为没有子菜单了,因此须要三个属性(要显示的文字,跳转的url,是否当前标识:'一个标志string(0)')就好。因为子菜单不止一个,因此,子子菜单这个确定也是一个数组,每一个子菜单也有属性,因此,也是一个对象属性,因此,数据大概以下面。
[ { 菜单名:'菜单名称 (首页)', 跳转的url:'url (/index)', 是否当前标识:'一个标志string (0)', 是否有子菜单:'是否 true||false' }, { 菜单名:'菜单名称 (首页)', 跳转的url:'url (/index)', 是否当前标识:'一个标志string (1)', 是否有子菜单:'是否 true||false', 是否展现:'是否 true||false', 子菜单:[ { 菜单名:'菜单名称 (首页)', 跳转的url:'url (/index)', 是否当前标识:'一个标志string (1_1)' }, { 菜单名:'菜单名称 (首页)', 跳转的url:'url (/index)', 是否当前标识:'一个标志string (1_2)' } ] } ]
最后,整理出来的数据就是!(tag这个标识数据,是我本身起的,你们也能够随意起。这个标识在下面会用到,在这里能够暂时不关注)
data(){ return { currentTag: '0', menus: [ { name: '首页', url: '/index', tag: '0', hasExtend: false, //是否有二级菜单 }, { name: '销售消息通知', url: '/saleR', tag: 'sale', hasExtend: true, //是否有二级菜单 fold: true, //是否展开 extend: [ { name: '待确认订单', url: '/order/list/0?ordConfirmStatus=0', tag: '1_1', }, { name: '待出库物流', url: '/logistics/logisticsList/0', tag: '1_2' }, { name: '待发货物流', url: '/logistics/logisticsList/1', tag: '1_3' }, { name: '待收货物流', url: '/logistics/logisticsList/2', tag: '1_4' }, { name: '待确认回款', url: '/cash/cashList/0', tag: '1_5' }, { name: '待开票申请', url: '/invoice/invoiceWriteList/0', tagIndex: '1_6' } ] }, { name: '销售管理', url: '/workbench', hasExtend: true, //是否有二级菜单 fold: true, //是否展开 extend: [ { name: '建立销售单', url: '/order/create', tag: '2_1' }, { name: '销售单管理', url: '/order/list', tag: '2_2' }, { name: '物流管理', url: '/logistics/logisticsList', tag: '2_3' }, { name: '回款管理', url: '/cash/cashList', tag: '2_4' }, { name: '开票管理', url: '/invoice/invoiceWriteList', tag: '2_9' }, { name: '票据管理', url: '/invoice/invoiceManageList', tag: '2_5' }, { name: '提成管理', url: '/commission/commissionList', tag: '2_6' }, { name: '提成设置', url: '/commission/commissionSet', tag: '2_7', }, { name: '合同管理', url: '/contract/contractList', tag: '2_8' }, ] }, ], } },
上面的数据相信你们都没什么问题,一一对应上就好(name--菜单名称, url--跳转的url,tag--当前的标识, hasExtend--是否有二级菜单,fold--是否展开extend--子菜单)
<template> <ul class="snav-menu" @click="show=false"> <li v-for="(item,index) in menus" :class="{active:item.fold,hasextend:item.hasExtend}"> <!--若是没有二级菜单--> <!--若是遍历到的标识等于当前的标识,就加上active类名,改变样式--> <!--点击事件为触发跳转路由,就好比点击‘首页’,就是跳转到‘首页’的对应的路由--> <a v-if="!item.hasExtend" href="javascript:;" class="tit" @click="switchNav(item.url,item.tag)" :class="{active:item.tag==currentTag}"> <em>{{item.name}}</em> </a> <!--若是有二级菜单--> <!--点击事件为触发子元素的显示或隐藏 好比点击‘销售消息通知’,就触发‘销售消息通知’下面子菜单的显示或者隐藏。若是显示就隐藏,隐藏就显示--> <a v-else href="javascript:;" class="tit" @click.stop="flod(index)"> <em>{{item.name}}</em> </a> <!--若是有二级菜单,遍历子菜单--> <!--若是有二级菜单,而且fold属性为true(子菜单展开显示)。就加上active类名,改变样式--> <div class="extend-nav level2" v-if="item.hasExtend" :class="{active:item.fold}"> <p v-for="(extend1,deep1) in item.extend"> <!--若是遍历到的标识等于当前的标识,就加上active类名,改变样式--> <!--点击切换路由(页面的操做)--> <a href="javascript:;" :class="{active:extend1.tag==currentTag}" @click="switchNav(extend1.url,extend1.tag)"> <em>{{extend1.name}}</em> </a> </p> </div> </li> </ul> </template>
flod
和switchNav
这个两个属性你们暂时不须要关注,下面会用到
遍历数据这个,你们看了上面的代码和注释,很好理解。我就很少说了!而后,在index.js里面,引入和注册这个组件。
而后index.html页面引用
而后ctrl+s一下,就能够看到效果了(前面在webpack.config.label.js
已经配置了热刷新。因此直接就能够看到效果,保存一下,或者改了一些代码后,一段时间没操做了,浏览器都会刷新,以下图)
看到运行结果,侧边栏出来了。而后,下一步!
关于侧边栏的操做,比较简单,无非就是点击菜单,跳转路由,标志当前项以及菜单下面子菜单的显示与隐藏。
1.首先,触发路由的跳转和标志当前项
咱们用到的是是上面代码的switchNav
这个方法;
咱们简单分析一下,这个方法,要实现跳转路由,标志当前项。就必需要接收两个参数(要跳转路由的url,当前的标识)。下面就实现下
switchNav(url,tag){ //标识当前导航 this.currentTag = tag; //router导航 this.$router.push({ 'path': url, 'query': { "tag": tag } }); }
看着代码是否是特别简单,每次点击的时候,用一个变量this.currentTag
记录当前的tag
,在html
遍历的时候,若是遍历道的tag
等于currentTag
的话,就加上active
的类名,标志当前项,不等于就不加类名。
好比一开始‘
this.currentTag='0'
,而后,首页的tag
又是等于'0'
,因此遍历道‘首页’的时候,就会给‘首页’那个菜单加上active
的类名’
而后跳转路由那个没有什么能够说的了,就把url当成参数传进去而已。
2.最后,实现菜单下面子菜单的显示与隐藏。这个方法就一行代码。
//展开收起导航面板 flod(index){ this.menus[index].fold = !this.menus[index].fold; },
由于只有两级,因此,只是根据传进来的索引(index
)来操做menus这个数组而已,把要操做的项的fold属性,取反。
运行一下,发现路由变了,当前项有标识了,子菜单的显示与隐藏也有了!原理也很简单。
运行完了,附上这个文件(snav-component.vue
)的代码大概就是这样
<template> <ul class="snav-menu" @click="show=false"> <li v-for="(item,index) in menus" :class="{active:item.fold,hasextend:item.hasExtend}"> <!--若是没有二级菜单--><!--若是遍历到的标识等于当前的标识,就加上active类名,改变样式--> <a v-if="!item.hasExtend" href="javascript:;" class="tit" @click="switchNav(item.url,item.tag)" :class="{active:item.tag==currentTag}"> <em>{{item.name}}</em> </a> <!--若是有二级菜单--> <a v-else href="javascript:;" class="tit" @click.stop="flod(index)"> <em>{{item.name}}</em> </a> <!--若是有二级菜单,遍历子菜单--><!--若是有二级菜单,而且fold属性为true(子菜单展开显示)。就加上active类名,改变样式--> <div class="extend-nav level2" v-if="item.hasExtend" :class="{active:item.fold}"> <p v-for="(extend1,deep1) in item.extend"> <!--若是遍历到的标识等于当前的标识,就加上active类名,改变样式--><!--点击切换路由(页面的操做)--> <a href="javascript:;" :class="{active:extend1.tag==currentTag}" @click="switchNav(extend1.url,extend1.tag)"> <em>{{extend1.name}}</em> </a> </p> </div> </li> </ul> </template> <script> export default{ data(){ return { //记录当前的标识 currentTag: '0', menus: [ { name: '首页', url: '/index', tag: '0', hasExtend: false, //是否有二级菜单 }, { name: '销售消息通知', url: '/saleR', tag: 'sale', hasExtend: true, //是否有二级菜单 fold: true, //是否展开 extend: [ { name: '待确认订单', url: '/order/list/0?ordConfirmStatus=0', tag: '1_1', }, { name: '待出库物流', url: '/logistics/logisticsList/0', tag: '1_2' }, { name: '待发货物流', url: '/logistics/logisticsList/1', tag: '1_3' }, { name: '待收货物流', url: '/logistics/logisticsList/2', tag: '1_4' }, { name: '待确认回款', url: '/cash/cashList/0', tag: '1_5' }, { name: '待开票申请', url: '/invoice/invoiceWriteList/0', tagIndex: '1_6' } ] }, { name: '销售管理', url: '/workbench', hasExtend: true, //是否有二级菜单 fold: true, //是否展开 extend: [ { name: '建立销售单', url: '/order/create', tag: '2_1' }, { name: '销售单管理', url: '/order/list', tag: '2_2' }, { name: '物流管理', url: '/logistics/logisticsList', tag: '2_3' }, { name: '回款管理', url: '/cash/cashList', tag: '2_4' }, { name: '开票管理', url: '/invoice/invoiceWriteList', tag: '2_9' }, { name: '票据管理', url: '/invoice/invoiceManageList', tag: '2_5' }, { name: '提成管理', url: '/commission/commissionList', tag: '2_6' }, { name: '提成设置', url: '/commission/commissionSet', tag: '2_7', }, { name: '合同管理', url: '/contract/contractList', tag: '2_8' }, ] }, ], } }, methods: { //切换组件 switchNav(url,tag){ //标识当前导航 this.currentTag = tag; //router导航 this.$router.push({ 'path': url, 'query': { "tag": tag } }); }, //展开收起导航面板 flod(index){ this.menus[index].fold = !this.menus[level1].fold; }, } } </script> <style lang="scss"> html,body,.zyl-admin-bd,.zyl-admin-wrap { width: 100%; height: 100%; } .zyl-admin-wrap{ position: fixed; } .zyl-admin-snav { position: fixed; z-index: 1; width: 210px; height: 100%; overflow-y: auto; background: #2a3542; box-shadow: 3px 0 30px rgba(0, 0, 0, .2); &::-webkit-scrollbar { width: 5px; height: 100%; border-radius: 2px; background: #424448; } &::-webkit-scrollbar-thumb { background: #A2A2A2; border-radius: 2px; } .snav-menu { margin-top: 10px; > li { margin:0 10px 10px 10px; &.hasextend { .tit { background: #35404d; } } &.active { background: #35404d; border-radius: 4px; overflow: hidden; .tit { background: #475669 !important; .icon-options-unfold { display: none; } .icon-options-fold { display: inline-block; } } .extend-nav { display: block; } } .tit { line-height: 22px; color: #aeb2b7; text-decoration: none; display: block; padding: 5px 0 5px 10px; font-size: 12px; outline: none; transition: all 0.3s ease; &:hover, &.active { background: #35404d; color: #fff; em { color: #FF6C60; } } em { display: inline-block; vertical-align: middle; font-style: normal; } } .extend-nav { display: none; &.active { display: block; } p { position: relative; a { display: block; font-size: 12px; padding: 6px 0; line-height: 25px; height: 25px; color: #aeb2b7; text-decoration: none; transition: all 0.3s ease; text-indent: 40px; &:hover, &.active { color: #FF6C60; background: #2e3844; .icon-arrow { display: inline-block; } } } } } } } } .zyl-admin-content { height: 100%; margin-left: 210px; overflow-y: auto; &::-webkit-scrollbar { width: 5px; height: 100%; border-radius: 2px; background: #424448; } &::-webkit-scrollbar-thumb { background: #A2A2A2; border-radius: 2px; } .wrapper { box-sizing: border-box; width: 100%; height: 100%; &::-webkit-scrollbar { width: 5px; height: 100%; border-radius: 2px; background: #424448; } &::-webkit-scrollbar-thumb { background: #A2A2A2; border-radius: 2px; } } } </style>
有一点要注意下,除了点击首页能看到一张图片以外,点击其它的菜单,右边都是白色的一片。由于其它的菜单的url。并无对应的组件。
好比:这个url在路由里面并无对应的组件。
怎么知道?在上一篇文件说到的router.js里面,并无配置‘/order/list/0?ordConfirmStatus=0
’这个url
对应的组件。因此在index.html
的<router-view></router-view>
输出的就是空白的一片。如今这里算是复习上一篇的内容了。也是给下一篇埋了一个伏笔。下一篇就讲这个配置。
今天就到这里了。主要就是一个主页面,主要是侧边栏的一个开发。这个侧边栏就是根据控制录用的变化。技术栈主要也就是vue
和vue-router
。原理就是根据路由的变化执行组件的切换。达到一个页面跳转的效果。下一篇就会说到,配置路由和路由对应的组件。但愿能帮到你们。最后仍是那句老话-若是你们发现我哪里写错了,或者是哪里写得很差,欢迎指点下。