为了账号安全,请及时绑定邮箱和手机立即绑定

webpack+vue项目实战(二,开发管理系统主页面)

1.前言

上篇文章(webpack+vue项目实战(一,搭建运行环境和相关配置))搭建了好了基本的一个项目目录,安好好了一些要用到的依赖,以及把项目跑了起来。接下来,我们就进行第二步的操作,第二步就是做好一个开发系统的主页面,这个页面主要也就是一个侧边栏,通过侧边栏的各个选项来进行操作(切换各个组件)。比如回款管理,订单管理,物流管理等等的操作。

2.顶部组件

开始属于排版这一块了,是时候在index.js引入一个公用样式了,相当于一个样式重置表。

clipboard.png

需求有一个,页面上面需要放一个退出的登录按钮,我就写了一个顶部组件的文件。首先就是创建这个文件

clipboard.png

代码如下

<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 scoped>     .topbar {         width: 100%;         height: 60px;     } </style>

然后入口文件(index.js)引用这个文件,并且在vue中注册组件import topbarComponent from './../components/admin_base/topbar.vue';

clipboard.png

然后入口模板文件,index.html引入标签
clipboard.png
页面结果(基于上一篇文章,已经跑起来的结果)

clipboard.png

页面上的class在公用样式里面有写好样式,还有一些样式是element-ui提供的,
<el-button>退出登录</el-button>就是element-ui提供的组件,在入口文件index.js已经引入了element-ui。这里直接用就好!

这个比较简单,我就不多说了。

3.侧边栏组件

这个侧边栏就是这篇文章的重点,也是整个项目操作的重点。先在目录上创建这样一个的侧边栏的组件文件。

clipboard.png

下面图片是我们要实现的效果,那些排版切图的样式我不多说了,相信不会难倒大家

clipboard.png

1.首先,创建一下这个侧边栏所需要的数据

从上面的效果图的看到。有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--子菜单)

2.遍历侧边栏的数据

<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>

flodswitchNav这个两个属性大家暂时不需要关注,下面会用到

遍历数据这个,大家看了上面的代码和注释,很好理解。我就不多说了!然后,在index.js里面,引入和注册这个组件。

clipboard.png

然后index.html页面引用
clipboard.png

然后ctrl+s一下,就可以看到效果了(前面在webpack.config.label.js已经配置了热刷新。所以直接就可以看到效果,保存一下,或者改了一些代码后,一段时间没操作了,浏览器都会刷新,如下图

clipboard.png

clipboard.png

看到运行结果,侧边栏出来了。然后,下一步!

3.给侧边栏写相关的一些操作

关于侧边栏的操作,比较简单,无非就是点击菜单,跳转路由,标志当前项以及菜单下面子菜单的显示与隐藏。
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的类名’

clipboard.png
然后跳转路由那个没有什么可以说的了,就把url当成参数传进去而已。

2.最后,实现菜单下面子菜单的显示与隐藏。这个方法就一行代码。

 //展开收起导航面板 flod(index){     this.menus[index].fold = !this.menus[index].fold; },

因为只有两级,所以,只是根据传进来的索引(index)来操作menus这个数组而已,把要操作的项的fold属性,取反。

运行一下,发现路由变了,当前项有标识了,子菜单的显示与隐藏也有了!原理也很简单。

clipboard.png

运行完了,附上这个文件(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>     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在路由里面并没有对应的组件。

clipboard.png

怎么知道?在上一篇文件说到的router.js里面,并没有配置‘/order/list/0?ordConfirmStatus=0’这个url对应的组件。所以在index.html<router-view></router-view>输出的就是空白的一片。现在这里算是复习上一篇的内容了。也是给下一篇埋了一个伏笔。下一篇就讲这个配置。
clipboard.png


点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
1.7万
获赞与收藏
966

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消