文章系列:

  • 基于Vue的管理后台设计(布局篇)
  • 基于Vue的管理后台设计(登录鉴权篇)
  • 基于Vue的管理后台设计(打包部署篇)

前言

我打算把接下来要写的几篇文章写成一个系列,用来记录一下如何基于Vue一步一步地搭建一个后台管理系统。

文章前传:

《Vue组件中引入jQuery》

《Webpack项目中引入Bootstrap4.x》

《Webpack项目中使用ToolTipster》

本篇文章就是这个系列的第一篇,将对整个系统的页面布局进行设计。在菜单目录树的实现中我们还将使用到前一篇 《前端无小事--Webpack项目中使用ToolTipster》中创建好的提示框组件,最终实现的页面效果如下。

Layout.vue

整个页面的布局分为三块区域:左侧菜单区、顶部菜单栏和内容区。

下面是它的完整代码:

<template><div class="layout"><div class="left-container" :style="{width: status.isCollapsed?'64px':'200px'}"><div class="logo-wrapper"><img style="width:50px;height:50px;" src="./DigitalX1.png" /></div><div class="menu-wrapper"><v-menu v-for="(menu,index) in this.menu_list" :key="index" :menu="menu" :status="status"></v-menu></div></div><div class="topbar-container" :style="{left: this.status.isCollapsed?'64px':'200px'}"><div class="btn btn-mini btn-success" @click="collapsed"><i class="icon-exchange"></i></div></div><div class="content-container" :style="{left: this.status.isCollapsed?'64px':'200px'}"><div class="content"><router-view></router-view></div></div></div>
</template>
<script>
import $ from "jquery";
import MenuItem from "../menu/MenuItem";export default {components: {"v-menu": MenuItem},data() {return {menu_list: [{path: "/home",title: "首页",icon: "icon-home icon-large"},{path: "/user",title: "用户管理",icon: "icon-user icon-large",children: [{ path: "/user/roles", title: "用户角色" },{ path: "/user/auths", title: "用户权限" }]},{path: "/sys",title: "系统管理",icon: "icon-heart icon-large",children: [{ path: "/sys/jobs", title: "定时任务" },{ path: "/sys/menus", title: "菜单管理" }]}],status: {isCollapsed: false,currentMenu: "首页",parentMenu: "首页"}};},methods: {collapsed: function() {if (this.status.isCollapsed) {this.status.isCollapsed = false;$(".l2").removeClass("hidden");} else {this.status.isCollapsed = true;$(".l2").addClass("hidden");}}}
};
</script>
<style scoped>
.left-container {position: fixed;top: 0;bottom: 0;left: 0;z-index: 99;background-color: #f6f6f6;transition: all 0.3s ease-in-out;box-shadow: 0 2px 4px 0 rgba(96, 125, 139, 0.9),0 0 6px 0 rgba(96, 125, 139, 0.4);
}
.logo-wrapper {display: block;margin: 20px 5px;text-align: center;
}
.topbar-container {position: fixed;right: 0;top: 0;height: 48px;line-height: 48px;padding: 0 10px;background-color: #f6f6f6;box-shadow: 0 2px 4px 0 rgba(96, 125, 139, 0.9),0 0 6px 0 rgba(96, 125, 139, 0.4);transition: all 0.3s ease-in-out;z-index: 99;
}
.content-container {position: fixed;right: 0;top: 48px;bottom: 0;padding: 16px;overflow: auto;transition: all 0.3s ease-in-out;
}
</style>

MenuItem.vue

MenuItem是一个自定义的菜单组件,每一个一级菜单都会被渲染成一个MenuItem实例,并包含了该一级菜单下面的二级菜单。

<template><div class="menu"><div class="menu-box l1"><vue-tooltipster:tooltipsterOptions="{side:'right'}"v-if="hasChildren && status.isCollapsed"><div:class="menu.title==status.parentMenu || menu.title==status.currentMenu? 'menu-item current-menu':'menu-item'"@click="menuClick($event)"><span class="icon-span"><i v-bind:class="menu.icon"></i></span></div><div slot="content"><liclass="tip-menu"v-for="(submenu,index) in menu.children":key="index":title="submenu.title"@click="tipMenuClick($event)"><span>{{submenu.title}}</span></li></div></vue-tooltipster><divv-else:class="menu.title==status.currentMenu? 'menu-item current-menu':'menu-item'"@click="menuClick($event)"><span class="icon-span"><i v-bind:class="menu.icon"></i></span><span v-if="!status.isCollapsed">{{menu.title}}</span><span class="arrow-span" v-if="hasChildren && !status.isCollapsed"><i v-if="showSubMenu" class="menu-arrow icon-angle-up icon-large"></i><i v-else class="menu-arrow icon-angle-down icon-large"></i></span></div><ul class="menu-box l2" v-if="showSubMenu && hasChildren && !status.isCollapsed"><liv-for="(submenu,index) in menu.children":key="index":class="submenu.title==status.currentMenu? 'menu-item current-menu':'menu-item'":title="submenu.title"@click="subMenuClick($event)"><span class="icon-span"></span><span v-if="!status.isCollapsed">{{submenu.title}}</span></li></ul></div></div>
</template>
<script>
import $ from "jquery";
import VueTooltipster from "../tooltip/V-ToolTip";export default {data() {return {showSubMenu: this.menu.title == this.status.parentMenu};},components: {VueTooltipster},props: ["menu", "status"],computed: {hasChildren: function() {return this.menu.children && this.menu.children.length > 0;}},methods: {menuClick: function(event) {var $this = $(event.currentTarget);var $arrow = $this.find(".menu-arrow");if (this.hasChildren) {if ($arrow.hasClass("icon-angle-down")) {$arrow.removeClass("icon-angle-down").addClass("icon-angle-up");this.showSubMenu = true;} else {$arrow.removeClass("icon-angle-up").addClass("icon-angle-down");this.showSubMenu = false;}} else {this.status.parentMenu = this.menu.title;this.status.currentMenu = this.menu.title;$(".menu-item").removeClass("current-menu");$this.addClass("current-menu");console.log("进入菜单:"+this.status.currentMenu);}},subMenuClick: function(event) {var $this = $(event.currentTarget);$(".menu-item").removeClass("current-menu");$this.addClass("current-menu");this.status.parentMenu = this.menu.title;this.status.currentMenu = $this.attr("title");console.log("进入菜单:"+this.status.currentMenu);},tipMenuClick: function(event) {var $this = $(event.currentTarget);this.status.currentMenu = $this.attr("title");this.status.parentMenu = this.menu.title;console.log("进入菜单:"+this.status.currentMenu);}}
};
</script>
<style scoped>
.menu-box {text-align: left;list-style: none;margin: 0;padding: 0;
}
.menu-item {cursor: pointer;color: black;line-height: 48px;white-space: nowrap;list-style: none;
}
.menu-item:hover {color: #7bb6e4;background-color: rgba(40, 167, 69, 0.5);
}
.current-menu {color: white !important;background-color: #28a745 !important;
}
.tip-menu {cursor: pointer;color: black;line-height: 48px;white-space: nowrap;list-style: none;
}
.tip-menu:hover {color: #28a745;
}
.icon-span {display: inline-block;width: 64px;padding-left: 22px;
}
.arrow-span {display: inline-block;position: absolute;right: 20px;
}
.hidden {display: none !important;
}
</style>

==============================我是分割线===============================

如果你想和我一样自己写一个目录树组件,我的建议是 最好不要自己写 ,原因很简单 可能出现的意外太多了,你很难能考虑到所有情况。所以,你的目录树组件好用不好用还不一定。我上面自己写的那个组件在实际使用时就出现了问题:当用户直接在地址栏输入地址时,如何定位到菜单;当用户输入一个错误的地址时,菜单要如何展示;云云。。。

明智的做法是使用开源的组件,省得去重复造轮子,关键是稳定性也是经过大家考验的。

例如,我使用的是 Element ,对上面的布局进行调整后代码如下:

<template><div class="layout"><div class="left-container" :style="{width: status.isCollapsed?'64px':'200px'}"><div class="logo-wrapper"><img style="width:50px;height:50px;" src="./DigitalX1.png" /></div><div class="menu-wrapper"><el-menutext-color="#000000"active-text-color="#ffffff"routerunique-opened:collapse="status.isCollapsed":default-active="$route.path"><template v-for="(menu, index) in menu_list"><el-menu-item class="menu-item" v-if="!menu.children" :index="menu.path" :key="index"><i :class="menu.icon" style="font-size:24px;"></i><span slot="title">{{menu.title}}</span></el-menu-item><el-submenu v-else :index="menu.path"><template slot="title"><i :class="menu.icon" style="font-size:24px;"></i><span slot="title">{{menu.title}}</span></template><el-menu-itemclass="menu-item"v-for="(subMenu, subIndex) in menu.children":index="subMenu.path":key="subIndex"><span slot="title" style="margin-left:13px;">{{subMenu.title}}</span></el-menu-item></el-submenu></template></el-menu></div></div><div class="topbar-container" :style="{left: this.status.isCollapsed?'64px':'200px'}"><div class="el-button el-button--default el-button--small" @click="collapsed"><i id="collapsedIcon" class="el-icon-s-fold"></i></div></div><div class="content-container" :style="{left: this.status.isCollapsed?'64px':'200px'}"><div class="content" style="height: 100%;"><router-view></router-view></div></div></div>
</template>
<script>
export default {data() {return {menu_list: [{path: "/home",title: "首页",icon: "el-icon-s-home"},{path: "/user",title: "用户管理",icon: "el-icon-user-solid",children: [{ path: "/user/roles", title: "用户角色" },{ path: "/user/auths", title: "用户权限" }]},{path: "/sys",title: "系统管理",icon: "el-icon-s-tools",children: [{ path: "/sys/jobs", title: "定时任务" },{ path: "/sys/menus", title: "菜单管理" }]}],status: {isCollapsed: false,parentMenu: "用户管理"}};},methods: {collapsed: function() {if (this.status.isCollapsed) {this.status.isCollapsed = false;$("#collapsedIcon").removeClass("el-icon-s-unfold").addClass("el-icon-s-fold");} else {this.status.isCollapsed = true;$("#collapsedIcon").removeClass("el-icon-s-fold").addClass("el-icon-s-unfold");}}}
};
</script>
<style scoped>
.left-container {position: fixed;top: 0;bottom: 0;left: 0;z-index: 99;background-color: #f6f6f6;transition: all 0.3s ease-in-out;box-shadow: 0 2px 4px 0 rgba(96, 125, 139, 0.9),0 0 6px 0 rgba(96, 125, 139, 0.4);
}
.logo-wrapper {display: block;margin: 20px 5px;text-align: center;
}
.topbar-container {position: fixed;right: 0;top: 0;height: 48px;line-height: 48px;padding: 0 10px;background-color: #f6f6f6;box-shadow: 0 2px 4px 0 rgba(96, 125, 139, 0.9),0 0 6px 0 rgba(96, 125, 139, 0.4);transition: all 0.3s ease-in-out;z-index: 99;
}
.content-container {position: fixed;right: 0;top: 48px;bottom: 0;padding: 16px;overflow: auto;transition: all 0.3s ease-in-out;
}
.menu-item.is-active {background-color: #28a745 !important;
}
</style>

代码少了不少,是不是清爽了许多!!!

基于Vue的管理后台设计(布局篇)相关推荐

  1. 干货|6个牛逼的基于Vue.js的后台控制面板,接私活必备

    JavaEE擅长的就是企业级应用,作为一个Java程序员,如果想自己徒手撸一个ERP.WMS之类的系统还是有一点挑战的,不过今天松哥要给大家介绍几款牛逼的基于Vue.js的后台管理控制面板,掌握这几款 ...

  2. 完整企业官网源码,前端基于Vue+ElementUI,后台基于基于core3 webapi,含数据库文件,含详情安装部署文档

    完整企业官网源码,前端基于Vue+ElementUI,后台基于基于core3 webapi,含数据库文件,含详情安装部署文档 完整代码下载地址:完整企业官网源码 某工程管理有限公司企业官网 前端 新版 ...

  3. 基于likeadmin通用管理后台搭建—高校科研管理系统

    前言 likeadmin是一款免费开源的通用后台框架系统,可以快速开发前后业务.代码生成器.API模块.uniapp端都已具备,下面是基于likeadmin通用管理后台搭建的-高校科研管理系统 产品背 ...

  4. 基于Vue的数据可视化设计框架,数据大屏可视化编辑器

    开发文档(★★★★★) 请访问 https://lizhensheng.github.io/vue-data-view/ 完整代码下载地址:基于Vue的数据可视化设计框架,数据大屏可视化编辑器 简介 ...

  5. 仿wordpress管理后台设计的后台管理框架

    仿wordpress管理后台设计的后台管理框架 本Markdown编辑器使用[StackEdit][6]修改而来,用它写博客,将会带来全新的体验哦: html的padding-top来实现整体下移,然 ...

  6. Vary Admin:基于Vue.js的后台管理模板

    简介 Vary Admin是基于Vue.js,搭配内置的vary-ui组件库组成的一套后台管理系统. Github: Vary Admin 在线预览:HomePage 效果展示 功能 多样化面板 基础 ...

  7. (附源码)nodejs+mysql+node基于vue框架的游戏商城设计及开发 -《夜幕》毕业设计262127

    Node.js<夜幕>游戏商城的开发 摘 要 现今人们的生活方式逐渐丰富,电脑和网络已经融入了人们生活中的滴滴点点,无时不刻的影响着我们的日常生活,网络游戏已经进入到了大多数人的生活之中. ...

  8. nodejs+mysql+node基于vue框架的游戏商城设计及开发 毕业设计-附源码262127

    Node.js<夜幕>游戏商城的开发 摘  要 现今人们的生活方式逐渐丰富,电脑和网络已经融入了人们生活中的滴滴点点,无时不刻的影响着我们的日常生活,网络游戏已经进入到了大多数人的生活之中 ...

  9. 3. 在WordPress管理后台撰写第一篇博客文章

    3. 发布第一篇博客文章 在前面的文章中,我们首先介绍了1. 购买云服务器和域名的基本操作,然后又成功2. 搭建最简单的博客网站,如果你还没完成上面这些操作,请提前点击查看. 这篇文章我们首先熟悉下网 ...

最新文章

  1. 并查集 ---- 扩展域并查集判二分图 + 循环模拟字典树 The 2020 ICPC Asia Macau Regional Contest C. Club Assignment (详解)
  2. python自动化测试框架pytest.pdf_Python自动化测试框架
  3. Dialog源码分析
  4. 三心二意,助你好运?
  5. Winform VS2015打包
  6. python turtle颜色rgb_turtle绘图总结
  7. 【飞秋】微软简化Visual Studio 非程序员也能开发软件
  8. 重新梳理下js中的深拷贝和浅拷贝
  9. linux运维高频命令汇总
  10. 九种跨域方式的实现原理,第一个就超惊艳!| 技术头条
  11. java filter与servlet,Servlet中的Filter和Listener之间的区别(Java EE)
  12. MSSQL为单独数据库创建登录账户
  13. 架构 - 洋葱图架构
  14. SQL教程及学习 我选择了《SQL必知必会》
  15. 数据库课设——简单的图书管理系统
  16. 4.7/4.8 磁盘挂载
  17. 3D资产大掌柜—Connecter
  18. js 递归函数(函数自己调用自己)
  19. 太空工程师-脚本-飞船姿态矫正
  20. 小驼峰命名法与大驼峰命名法

热门文章

  1. 利用正态分布中三西格玛原理检查坏值
  2. 哪个PDF文档翻译软件好用?PDF文档翻译的方法是什么?
  3. 【持续更新】一些PS的快捷键使用(看敬伟老师网课)
  4. 【鹏哥C语言网课笔记】初始结构体
  5. mysql数据库错误1317_我的mysql数据库好像是连接不上,两天了找不到错误,急求大家的帮助...
  6. SpringBoot从入门到精通-说说Excel文件下载文件解决 格式和扩展名不匹配。文件可能已损坏或不安全
  7. RHCSA学习 --- 在VMware上创建虚拟机并安装红帽linux系统
  8. 编码,加密,hash
  9. 政府停摆致白宫无法宴客 总统叫外卖招待冠军球队
  10. Qt MVC之自定义模型