组件封装

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

组件结构

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

代码一览

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

Home.vue

<template>
<div class="container">
<!-- 导航菜单栏 -->
<MenuBar></MenuBar>
<!-- 头部区域 -->
<HeadBar></HeadBar>
<!-- 主内容区域 -->
<Main></Main>
</div>
</template> <script>
import HeadBar from "./HeadBar/HeadBar"
import MenuBar from "./MenuBar/MenuBar"
import Main from "./Main/Main"
export default {
components:{
HeadBar,
MenuBar,
Main
}
};
</script> <style scoped lang="scss">
.container {
position:absolute;
top: 0px;
left: 0px;
right: 0px;
background: #4b5f6e;
}
</style>

HeadBar.vue

<template>
<div class="container">
<!-- 导航菜单隐藏显示切换 -->
<span class="collapse-switcher" @click.prevent="collapse">
<i class="el-icon-menu"></i>
</span>
<!-- 导航菜单 -->
<span class="nav-bar">
<el-menu :default-active="activeIndex" class="el-menu-demo" text-color="#fff"
active-text-color="#ffd04b" mode="horizontal" @select="selectNavBar()">
<el-menu-item index="1" @click="$router.push('/')">{{$t("common.home")}}</el-menu-item>
<el-menu-item index="2">{{$t("common.doc")}}</el-menu-item>
<el-menu-item index="3">{{$t("common.msgCenter")}}</el-menu-item>
</el-menu>
</span>
<span class="tool-bar">
<!-- 主题切换 -->
<ThemePicker class="theme-picker"></ThemePicker>
<!-- 语言切换 -->
<LangSelector class="lang-selector"></LangSelector>
<!-- 用户信息 -->
<el-dropdown class="user-info-dropdown" trigger="hover">
<span class="el-dropdown-link"><img :src="this.userAvatar" /> {{username}}</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>{{$t("common.myMsg")}}</el-dropdown-item>
<el-dropdown-item>{{$t("common.config")}}</el-dropdown-item>
<el-dropdown-item divided @click.native="logout">{{$t("common.logout")}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</span>
</div>
</template> <script>
import mock from "@/mock/index.js";
import ThemePicker from "@/components/ThemePicker"
import LangSelector from "@/components/LangSelector"
export default {
components:{
ThemePicker,
LangSelector
},
data() {
return {
isCollapse: false,
username: "Louis",
userAvatar: "",
activeIndex: '1'
};
},
methods: {
selectNavBar(key, keyPath) {
console.log(key, keyPath)
},
// 语言切换
handleCommand(command) {
let array = command.split(':')
let lang = array[0] === '' ? 'zh_cn' : array[0]
let label = array[1]
document.getElementById("language").innerHTML = label
this.$i18n.locale = lang
},
//折叠导航栏
collapse: function() {
this.isCollapse = !this.isCollapse;
},
//退出登录
logout: function() {
var _this = this;
this.$confirm("确认退出吗?", "提示", {
type: "warning"
})
.then(() => {
sessionStorage.removeItem("user");
this.$router.push
("/login");
})
.catch(() => {});
}
},
mounted() {
this.sysName = "I like Kitty";
var user = sessionStorage.getItem("user");
if (user) {
this.userName = user;
this.userAvatar = require("@/assets/user.png");
}
}
};
</script> <style scoped lang="scss">
.container {
position: absolute;
left: 200px;
right: 0px;
height: 60px;
line-height: 60px;
.collapse-switcher {
width: 40px;
float: left;
cursor: pointer;
border-color: rgba(111, 123, 131, 0.8);
border-left-width: 1px;
border-left-style: solid;
border-right-width: 1px;
border-right-style: solid;
color: white;
background: #504e6180;
}
.nav-bar {
margin-left: auto;
float: left;
.el-menu {
background: #504e6180;
}
}
.tool-bar {
float: right;
.theme-picker {
padding-right: 10px;
}
.lang-selector {
padding-right: 10px;
font-size: 15px;
color: #fff;
cursor: pointer;
}
.user-info-dropdown {
font-size: 20px;
padding-right: 20px;
color: #fff;
cursor: pointer;
img {
width: 40px;
height: 40px;
border-radius: 10px;
margin: 10px 0px 10px 10px;
float: right;
}
}
}
}
</style>

MenuBar.vue

<template>
<div class="menu-bar-container">
<!-- logo -->
<div class="logo" :class="isCollapse?'menu-bar-collapse-width':'menu-bar-width'">
<img :src="this.logo" /> <div>{{isCollapse?'':sysName}}</div>
</div>
<!-- 导航菜单 -->
<el-menu default-active="1-1" :class="isCollapse?'menu-bar-collapse-width':'menu-bar-width'" @open="handleopen" @close="handleclose" @select="handleselect" :collapse="isCollapse">
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span slot="title">{{$t("sys.sysMng")}}</span>
</template>
<el-menu-item index="1-1" @click="$router.push('user')">{{$t("sys.userMng")}}</el-menu-item>
<el-menu-item index="1-2" @click="$router.push('dept')">{{$t("sys.deptMng")}}</el-menu-item>
<el-menu-item index="1-3" @click="$router.push('role')">{{$t("sys.roleMng")}}</el-menu-item>
<el-menu-item index="1-4" @click="$router.push('menu')">{{$t("sys.menuMng")}}</el-menu-item>
<el-menu-item index="1-5" @click="$router.push('log')">{{$t("sys.logMng")}}</el-menu-item>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-location"></i>
<span slot="title">{{$t("sys.sysMonitor")}}</span>
</template>
</el-submenu>
<el-menu-item index="3" disabled>
<i class="el-icon-document"></i>
<span slot="title">{{$t("sys.nav3")}}</span>
</el-menu-item>
<el-menu-item index="4">
<i class="el-icon-setting"></i>
<span slot="title">{{$t("sys.nv4")}}</span>
</el-menu-item>
</el-menu>
</div>
</template> <script>
export default {
data() {
return {
isCollapse: false,
sysName: "",
logo: "",
};
},
methods: {
handleopen() {
console.log('handleopen');
},
handleclose() {
console.log('handleclose');
},
handleselect(a, b) {
console.log('handleselect');
}
},
mounted() {
this.sysName = "I like Kitty";
this.logo = require("@/assets/logo.png");
}
};
</script> <style scoped lang="scss">
.menu-bar-container {
.el-menu {
position:absolute;
top: 60px;
bottom: 0px;
text-align: left;
}
.logo {
position:absolute;
top: 0px;
height: 60px;
line-height: 60px;
background: #4b5f6e;
img {
width: 40px;
height: 40px;
border-radius: 0px;
margin: 10px 10px 10px 10px;
float: left;
}
div {
font-size: 22px;
color: white;
text-align: left;
}
}
.menu-bar-width {
width: 200px;
}
.menu-bar-collapse-width {
width: 65px;
}
}
</style>

Main.vue

<template>
<div class="container">
<el-breadcrumb separator="/" class="breadcrumb">
<el-breadcrumb-item v-for="item in $route.matched" :key="item.path">
<a href="www.baidu.com">{{ item.name }}</a>
</el-breadcrumb-item>
</el-breadcrumb>
<transition name="fade" mode="out-in">
<router-view></router-view>
</transition>
</div>
</template> <script>
export default {
data() {
return {
};
},
methods: { },
mounted() { }
};
</script> <style scoped lang="scss">
.container {
position: absolute;
top: 60px;
bottom: 0px;
left: 200px;
right: 0px;
.breadcrumb {
padding: 10px;
border-color: rgba(38, 86, 114, 0.2);
border-bottom-width: 1px;
border-bottom-style: solid;
background: rgba(138, 158, 170, 0.2);
}
}
</style>

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

LangSelector/index.js

<template>
<el-dropdown class="lang-selector" @command="handleCommand">
<span class="el-dropdown-link">
<span id="language">中文</span><i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="zh_cn:中文">中文</el-dropdown-item>
<el-dropdown-item command="en_us:English">English</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template> <script>
export default {
methods: {
// 语言切换
handleCommand(command) {
let array = command.split(':')
let lang = array[0] === '' ? 'zh_cn' : array[0]
let label = array[1]
document.getElementById("language").innerHTML = label
this.$i18n.locale = lang
}
}
}
</script>

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

import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/views/Login'
import NotFound from '@/views/404'
import Home from '@/views/Home'
import Intro from '@/views/Intro'
import User from '@/views/SysMng/User'
import Dept from '@/views/SysMng/Dept'
import Role from '@/views/SysMng/Role'
import Menu from '@/views/SysMng/Menu'
import Log from '@/views/SysMng/Log' Vue.use(Router) const router = new Router({
routes: [
{
path: '/',
name: '首页',
component: Home,
children: [
{ path: '', component: Intro, name: '系统介绍' },
{ path: '/user', component: User, name: '用户管理' },
{ path: '/dept', component: Dept, name: '机构管理' },
{ path: '/role', component: Role, name: '角色管理' },
{ path: '/menu', component: Menu, name: '菜单管理' },
{ path: '/log', component: Log, name: '日志管理' }
]
},
{
path: '/login',
name: '登录',
component: Login
}
,{
path: '/404',
name: 'notFound',
component: NotFound
}
]
}) router.beforeEach((to, from, next) => {
// 登录界面登录成功之后,会把用户信息保存在会话
// 存在时间为会话生命周期,页面关闭即失效。
let user = sessionStorage.getItem('user');
if (to.path == '/login') {
// 如果是访问登录界面,如果用户会话信息存在,代表已登录过,跳转到主页
if(user) {
next({ path: '/' })
} else {
next()
}
} else {
// 如果访问非登录界面,且户会话信息不存在,代表未登录,则跳转到登录界面
if (!user) {
next({ path: '/login' })
} else {
next()
}
}
}) 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. leecode第四题(寻找两个有序数组的中位数)

    题解: class Solution { public: double findMedianSortedArrays(vector<int>& nums1, vector<i ...

  2. => js 中箭头函数使用总结

    箭头函数感性认识 箭头函数 是在es6 中添加的一种规范 x => x * x 相当于 function(x){return x*x} 箭头函数相当于 匿名函数, 简化了函数的定义. 语言的发展 ...

  3. 新建ng工程

    有问题多看官网文档https://www.angular.cn/guide/quickstart 1 在远程仓库建立 1个完全空的仓库,不要建立readme.MD  ng cli创建时会创建readm ...

  4. MYSQL的常用函数(字符串函数)

    ASCII(char)返回字符的ASCII码值 BIT_LENGTH(str)返回字符串的比特长度 CONCAT(s1,s2...,sn)将s1,s2...,sn连接成字符串 CONCAT_WS(se ...

  5. Codeforces 233 D - Table

    D - Table 思路:dp 首先,第i列的个数肯定和第i - n列个数一样,假设[i - n + 1, i - 1] 之间的个数之和为x,那么第i列和第i-n列的个数应该是n - x 那么我们可以 ...

  6. ace后台管理系统扁平化框架

    Bootstrap ACE后台管理界面模板(扁平化) 所属分类:后台模板 文件大小:1.22 MB 阅读:236697次 下载:55929次 来源:www.daimajiayuan.com 分享到:更 ...

  7. English trip V1 - 24. Accommodations Teacher:Maple Key: make suggestions 提出建议

    In this lesson you will learn to make suggestions. 在本课程中,您将学习如何提出建议. 课上内容(Lesson) Which place  would ...

  8. 20 Interesting WPF Projects on CodePlex

    20 Interesting WPF Projects on CodePlex (Some for Silverlight too) Pete Brown - 22 November 2010   I ...

  9. NYOJ - 整数划分(四)

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=746 要求对一个n的整数插入m个乘号,求最大结果. 构造dp:dp[i][j]表示枚举至j ...

  10. HTML页面加载完毕后运行的js

    Js方法:<script type=”text/javascript”> window.onload=function (){ var userName=”xiaoming”; alert ...