组件封装

为了避免组件代码的臃肿,这里对主要的功能部件进行封装,保证代码的模块化和简洁度。

组件结构

组件封装重构后,试图组件结构如下图所示

代码一览

Home组件被简化,包含导航、头部和主内容三个组件。

Home.vue

  1. <template>
  2. <div class="container">
  3. <!-- 导航菜单栏 -->
  4. <MenuBar></MenuBar>
  5. <!-- 头部区域 -->
  6. <HeadBar></HeadBar>
  7. <!-- 主内容区域 -->
  8. <Main></Main>
  9. </div>
  10. </template>
  11.  
  12. <script>
  13. import HeadBar from "./HeadBar/HeadBar"
  14. import MenuBar from "./MenuBar/MenuBar"
  15. import Main from "./Main/Main"
  16. export default {
  17. components:{
  18. HeadBar,
  19. MenuBar,
  20. Main
  21. }
  22. };
  23. </script>
  24.  
  25. <style scoped lang="scss">
  26. .container {
  27. position:absolute;
  28. top: 0px;
  29. left: 0px;
  30. right: 0px;
  31. background: #4b5f6e;
  32. }
  33. </style>

HeadBar.vue

  1. <template>
  2. <div class="container">
  3. <!-- 导航菜单隐藏显示切换 -->
  4. <span class="collapse-switcher" @click.prevent="collapse">
  5. <i class="el-icon-menu"></i>
  6. </span>
  7. <!-- 导航菜单 -->
  8. <span class="nav-bar">
  9. <el-menu :default-active="activeIndex" class="el-menu-demo" text-color="#fff"
  10. active-text-color="#ffd04b" mode="horizontal" @select="selectNavBar()">
  11. <el-menu-item index="1" @click="$router.push('/')">{{$t("common.home")}}</el-menu-item>
  12. <el-menu-item index="2">{{$t("common.doc")}}</el-menu-item>
  13. <el-menu-item index="3">{{$t("common.msgCenter")}}</el-menu-item>
  14. </el-menu>
  15. </span>
  16. <span class="tool-bar">
  17. <!-- 主题切换 -->
  18. <ThemePicker class="theme-picker"></ThemePicker>
  19. <!-- 语言切换 -->
  20. <LangSelector class="lang-selector"></LangSelector>
  21. <!-- 用户信息 -->
  22. <el-dropdown class="user-info-dropdown" trigger="hover">
  23. <span class="el-dropdown-link"><img :src="this.userAvatar" /> {{username}}</span>
  24. <el-dropdown-menu slot="dropdown">
  25. <el-dropdown-item>{{$t("common.myMsg")}}</el-dropdown-item>
  26. <el-dropdown-item>{{$t("common.config")}}</el-dropdown-item>
  27. <el-dropdown-item divided @click.native="logout">{{$t("common.logout")}}</el-dropdown-item>
  28. </el-dropdown-menu>
  29. </el-dropdown>
  30. </span>
  31. </div>
  32. </template>
  33.  
  34. <script>
  35. import mock from "@/mock/index.js";
  36. import ThemePicker from "@/components/ThemePicker"
  37. import LangSelector from "@/components/LangSelector"
  38. export default {
  39. components:{
  40. ThemePicker,
  41. LangSelector
  42. },
  43. data() {
  44. return {
  45. isCollapse: false,
  46. username: "Louis",
  47. userAvatar: "",
  48. activeIndex: '1'
  49. };
  50. },
  51. methods: {
  52. selectNavBar(key, keyPath) {
  53. console.log(key, keyPath)
  54. },
  55. // 语言切换
  56. handleCommand(command) {
  57. let array = command.split(':')
  58. let lang = array[0] === '' ? 'zh_cn' : array[0]
  59. let label = array[1]
  60. document.getElementById("language").innerHTML = label
  61. this.$i18n.locale = lang
  62. },
  63. //折叠导航栏
  64. collapse: function() {
  65. this.isCollapse = !this.isCollapse;
  66. },
  67. //退出登录
  68. logout: function() {
  69. var _this = this;
  70. this.$confirm("确认退出吗?", "提示", {
  71. type: "warning"
  72. })
  73. .then(() => {
  74. sessionStorage.removeItem("user");
  75. this.$router.push
  76. ("/login");
  77. })
  78. .catch(() => {});
  79. }
  80. },
  81. mounted() {
  82. this.sysName = "I like Kitty";
  83. var user = sessionStorage.getItem("user");
  84. if (user) {
  85. this.userName = user;
  86. this.userAvatar = require("@/assets/user.png");
  87. }
  88. }
  89. };
  90. </script>
  91.  
  92. <style scoped lang="scss">
  93. .container {
  94. position: absolute;
  95. left: 200px;
  96. right: 0px;
  97. height: 60px;
  98. line-height: 60px;
  99. .collapse-switcher {
  100. width: 40px;
  101. float: left;
  102. cursor: pointer;
  103. border-color: rgba(111, 123, 131, 0.8);
  104. border-left-width: 1px;
  105. border-left-style: solid;
  106. border-right-width: 1px;
  107. border-right-style: solid;
  108. color: white;
  109. background: #504e6180;
  110. }
  111. .nav-bar {
  112. margin-left: auto;
  113. float: left;
  114. .el-menu {
  115. background: #504e6180;
  116. }
  117. }
  118. .tool-bar {
  119. float: right;
  120. .theme-picker {
  121. padding-right: 10px;
  122. }
  123. .lang-selector {
  124. padding-right: 10px;
  125. font-size: 15px;
  126. color: #fff;
  127. cursor: pointer;
  128. }
  129. .user-info-dropdown {
  130. font-size: 20px;
  131. padding-right: 20px;
  132. color: #fff;
  133. cursor: pointer;
  134. img {
  135. width: 40px;
  136. height: 40px;
  137. border-radius: 10px;
  138. margin: 10px 0px 10px 10px;
  139. float: right;
  140. }
  141. }
  142. }
  143. }
  144. </style>

MenuBar.vue

  1. <template>
  2. <div class="menu-bar-container">
  3. <!-- logo -->
  4. <div class="logo" :class="isCollapse?'menu-bar-collapse-width':'menu-bar-width'">
  5. <img :src="this.logo" /> <div>{{isCollapse?'':sysName}}</div>
  6. </div>
  7. <!-- 导航菜单 -->
  8. <el-menu default-active="1-1" :class="isCollapse?'menu-bar-collapse-width':'menu-bar-width'" @open="handleopen" @close="handleclose" @select="handleselect" :collapse="isCollapse">
  9. <el-submenu index="1">
  10. <template slot="title">
  11. <i class="el-icon-location"></i>
  12. <span slot="title">{{$t("sys.sysMng")}}</span>
  13. </template>
  14. <el-menu-item index="1-1" @click="$router.push('user')">{{$t("sys.userMng")}}</el-menu-item>
  15. <el-menu-item index="1-2" @click="$router.push('dept')">{{$t("sys.deptMng")}}</el-menu-item>
  16. <el-menu-item index="1-3" @click="$router.push('role')">{{$t("sys.roleMng")}}</el-menu-item>
  17. <el-menu-item index="1-4" @click="$router.push('menu')">{{$t("sys.menuMng")}}</el-menu-item>
  18. <el-menu-item index="1-5" @click="$router.push('log')">{{$t("sys.logMng")}}</el-menu-item>
  19. </el-submenu>
  20. <el-submenu index="2">
  21. <template slot="title">
  22. <i class="el-icon-location"></i>
  23. <span slot="title">{{$t("sys.sysMonitor")}}</span>
  24. </template>
  25. </el-submenu>
  26. <el-menu-item index="3" disabled>
  27. <i class="el-icon-document"></i>
  28. <span slot="title">{{$t("sys.nav3")}}</span>
  29. </el-menu-item>
  30. <el-menu-item index="4">
  31. <i class="el-icon-setting"></i>
  32. <span slot="title">{{$t("sys.nv4")}}</span>
  33. </el-menu-item>
  34. </el-menu>
  35. </div>
  36. </template>
  37.  
  38. <script>
  39. export default {
  40. data() {
  41. return {
  42. isCollapse: false,
  43. sysName: "",
  44. logo: "",
  45. };
  46. },
  47. methods: {
  48. handleopen() {
  49. console.log('handleopen');
  50. },
  51. handleclose() {
  52. console.log('handleclose');
  53. },
  54. handleselect(a, b) {
  55. console.log('handleselect');
  56. }
  57. },
  58. mounted() {
  59. this.sysName = "I like Kitty";
  60. this.logo = require("@/assets/logo.png");
  61. }
  62. };
  63. </script>
  64.  
  65. <style scoped lang="scss">
  66. .menu-bar-container {
  67. .el-menu {
  68. position:absolute;
  69. top: 60px;
  70. bottom: 0px;
  71. text-align: left;
  72. }
  73. .logo {
  74. position:absolute;
  75. top: 0px;
  76. height: 60px;
  77. line-height: 60px;
  78. background: #4b5f6e;
  79. img {
  80. width: 40px;
  81. height: 40px;
  82. border-radius: 0px;
  83. margin: 10px 10px 10px 10px;
  84. float: left;
  85. }
  86. div {
  87. font-size: 22px;
  88. color: white;
  89. text-align: left;
  90. }
  91. }
  92. .menu-bar-width {
  93. width: 200px;
  94. }
  95. .menu-bar-collapse-width {
  96. width: 65px;
  97. }
  98. }
  99. </style>

Main.vue

  1. <template>
  2. <div class="container">
  3. <el-breadcrumb separator="/" class="breadcrumb">
  4. <el-breadcrumb-item v-for="item in $route.matched" :key="item.path">
  5. <a href="www.baidu.com">{{ item.name }}</a>
  6. </el-breadcrumb-item>
  7. </el-breadcrumb>
  8. <transition name="fade" mode="out-in">
  9. <router-view></router-view>
  10. </transition>
  11. </div>
  12. </template>
  13.  
  14. <script>
  15. export default {
  16. data() {
  17. return {
  18. };
  19. },
  20. methods: {
  21.  
  22. },
  23. mounted() {
  24.  
  25. }
  26. };
  27. </script>
  28.  
  29. <style scoped lang="scss">
  30. .container {
  31. position: absolute;
  32. top: 60px;
  33. bottom: 0px;
  34. left: 200px;
  35. right: 0px;
  36. .breadcrumb {
  37. padding: 10px;
  38. border-color: rgba(38, 86, 114, 0.2);
  39. border-bottom-width: 1px;
  40. border-bottom-style: solid;
  41. background: rgba(138, 158, 170, 0.2);
  42. }
  43. }
  44. </style>

国际化语言切换也被封装成为了组件 LangSelector

LangSelector/index.js

  1. <template>
  2. <el-dropdown class="lang-selector" @command="handleCommand">
  3. <span class="el-dropdown-link">
  4. <span id="language">中文</span><i class="el-icon-arrow-down el-icon--right"></i>
  5. </span>
  6. <el-dropdown-menu slot="dropdown">
  7. <el-dropdown-item command="zh_cn:中文">中文</el-dropdown-item>
  8. <el-dropdown-item command="en_us:English">English</el-dropdown-item>
  9. </el-dropdown-menu>
  10. </el-dropdown>
  11. </template>
  12.  
  13. <script>
  14. export default {
  15. methods: {
  16. // 语言切换
  17. handleCommand(command) {
  18. let array = command.split(':')
  19. let lang = array[0] === '' ? 'zh_cn' : array[0]
  20. let label = array[1]
  21. document.getElementById("language").innerHTML = label
  22. this.$i18n.locale = lang
  23. }
  24. }
  25. }
  26. </script>

组件封装重构之后,同步修改路由配置

  1. import Vue from 'vue'
  2. import Router from 'vue-router'
  3. import Login from '@/views/Login'
  4. import NotFound from '@/views/404'
  5. import Home from '@/views/Home'
  6. import Intro from '@/views/Intro'
  7. import User from '@/views/SysMng/User'
  8. import Dept from '@/views/SysMng/Dept'
  9. import Role from '@/views/SysMng/Role'
  10. import Menu from '@/views/SysMng/Menu'
  11. import Log from '@/views/SysMng/Log'
  12.  
  13. Vue.use(Router)
  14.  
  15. const router = new Router({
  16. routes: [
  17. {
  18. path: '/',
  19. name: '首页',
  20. component: Home,
  21. children: [
  22. { path: '', component: Intro, name: '系统介绍' },
  23. { path: '/user', component: User, name: '用户管理' },
  24. { path: '/dept', component: Dept, name: '机构管理' },
  25. { path: '/role', component: Role, name: '角色管理' },
  26. { path: '/menu', component: Menu, name: '菜单管理' },
  27. { path: '/log', component: Log, name: '日志管理' }
  28. ]
  29. },
  30. {
  31. path: '/login',
  32. name: '登录',
  33. component: Login
  34. }
  35. ,{
  36. path: '/404',
  37. name: 'notFound',
  38. component: NotFound
  39. }
  40. ]
  41. })
  42.  
  43. router.beforeEach((to, from, next) => {
  44. // 登录界面登录成功之后,会把用户信息保存在会话
  45. // 存在时间为会话生命周期,页面关闭即失效。
  46. let user = sessionStorage.getItem('user');
  47. if (to.path == '/login') {
  48. // 如果是访问登录界面,如果用户会话信息存在,代表已登录过,跳转到主页
  49. if(user) {
  50. next({ path: '/' })
  51. } else {
  52. next()
  53. }
  54. } else {
  55. // 如果访问非登录界面,且户会话信息不存在,代表未登录,则跳转到登录界面
  56. if (!user) {
  57. next({ path: '/login' })
  58. } else {
  59. next()
  60. }
  61. }
  62. })
  63.  
  64. export default router

测试效果

封装重构之后,启动界面,效果跟之前差别不大。

Vue + Element UI 实现权限管理系统 (功能组件封装)的更多相关文章

  1. Vue + Element UI 实现权限管理系统

    Vue + Element UI 实现权限管理系统 前端篇(一):搭建开发环境 https://www.cnblogs.com/xifengxiaoma/p/9533018.html

  2. Vue + Element UI 实现权限管理系统 前端篇(七):功能组件封装

    组件封装 为了避免组件代码的臃肿,这里对主要的功能部件进行封装,保证代码的模块化和简洁度. 组件结构 组件封装重构后,试图组件结构如下图所示 代码一览 Home组件被简化,包含导航.头部和主内容三个组 ...

  3. Vue + Element UI 实现权限管理系统 前端篇(十三):页面权限控制

    权限控制方案 既然是后台权限管理系统,当然少不了权限控制啦,至于权限控制,前端方面当然就是对页面资源的访问和操作控制啦. 前端资源权限主要又分为两个部分,即导航菜单的查看权限和页面增删改操作按钮的操作 ...

  4. Vue + Element UI 实现权限管理系统 前端篇(十二):用户管理模块

    用户管理模块 添加接口 在 http/moduls/user.js 中添加用户管理相关接口. import axios from '../axios' /* * 用户管理模块 */ // 保存 exp ...

  5. Vue + Element UI 实现权限管理系统 (管理应用状态)

    使用 Vuex 管理应用状态 1. 引入背景 像先前我们是有导航菜单栏收缩和展开功能的,但是因为组件封装的原因,隐藏按钮在头部组件,而导航菜单在导航菜单组件,这样就涉及到了组件收缩状态的共享问题.收缩 ...

  6. Vue + Element UI 实现权限管理系统 前端篇(八):管理应用状态

    使用 Vuex 管理应用状态 1. 引入背景 像先前我们是有导航菜单栏收缩和展开功能的,但是因为组件封装的原因,隐藏按钮在头部组件,而导航菜单在导航菜单组件,这样就涉及到了组件收缩状态的共享问题.收缩 ...

  7. Vue + Element UI 实现权限管理系统 前端篇(十一):第三方图标库

    使用第三方图标库 用过Elment的同鞋都知道,Element UI提供的字体图符少之又少,实在是不够用啊,幸好现在有不少丰富的第三方图标库可用,引入也不会很麻烦. Font Awesome Font ...

  8. Vue + Element UI 实现权限管理系统(第三方图标库)

    使用第三方图标库 用过Elment的同鞋都知道,Element UI提供的字体图符少之又少,实在是不够用啊,幸好现在有不少丰富的第三方图标库可用,引入也不会很麻烦. Font Awesome Font ...

  9. Vue + Element UI 实现权限管理系统 前端篇(十四):菜单功能实现

    菜单功能实现 菜单接口封装 菜单管理是一个对菜单树结构的增删改查操作. 提供一个菜单查询接口,查询整颗菜单树形结构. http/modules/menu.js 添加 findMenuTree 接口. ...

随机推荐

  1. Given d and e, factorize N to attack RSA

    题目如下: RSA算法的使用一般要求每个不同的用户有一个独立的模数N.有天,Bob脑洞大开,认为似乎没有必要这样做.只需要一个模数N,然后给不同的用户分发不同的e和d就好了.可惜这种做法有严重的安全漏 ...

  2. Android requestCode的限制

    一. why ? 由于才疏学浅,在开发中requestCode的让我很困惑.困惑是因为什么呢,是因为弄混了.要想弄明白,不困惑,来想一想用到requestCode的地方: ① startActivit ...

  3. List、Map、Set的区别与联系

    重复和有序 List 存储的元素是有顺序的,并且值允许重复: Map 元素按键值对存储,无放入顺序 ,它的键是不允许重复的,但是值是允许重复的: Set 存储的元素是无顺序的,并且不允许重复,元素虽然 ...

  4. 使用VSCode如何从github拉取项目

    转载自:https://blog.csdn.net/sunqy1995/article/details/81517159 1.开vscode使用CTRL+`或者点击查看到集成终端打开控制终端 2. 在 ...

  5. winfrom 动态添加控件,以及删除

      private void btnadd_Click(object sender, EventArgs e)         {             int fileCount = 0;     ...

  6. 解码字符串 Decode String

    2018-11-14 17:56:12 问题描述: 问题求解: 方法一.递归求解 最直观的解法就是递归来求了,并且很显然的这个问题可以使用递归来进行求解. public String decodeSt ...

  7. php递归方法

    <?phpheader("Content-type:text/html;charset=utf-8");$city=array( array('id'=>1,'name ...

  8. Spring Boot入门第三天:配置日志系统和Druid数据库连接池。

    原文链接 一.日志管理 1.在application.properties文件中加入如下内容: logging.level.root=WARN logging.level.org.springfram ...

  9. You Don't Know JS: Scope & Closures (第4章: Hoisting)

    Chapter4: Hoisting 变量附加到哪个层次的scope,由它们在哪里和如何声明(let, var)来决定. Function scope/Block scope都有相同的法则:任何变量在 ...

  10. 通过.frm和.ibd恢复mysql数据

    .frm文件:保存了每个表的元数据,包括表结构的定义等: .ibd文件:InnoDB引擎开启了独立表空间(my.ini中配置innodb_file_per_table = 1)产生的存放该表的数据和索 ...