Vue + Element UI 实现权限管理系统 (功能组件封装)
组件封装
为了避免组件代码的臃肿,这里对主要的功能部件进行封装,保证代码的模块化和简洁度。
组件结构
组件封装重构后,试图组件结构如下图所示
代码一览
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 实现权限管理系统 (功能组件封装)的更多相关文章
- Vue + Element UI 实现权限管理系统
Vue + Element UI 实现权限管理系统 前端篇(一):搭建开发环境 https://www.cnblogs.com/xifengxiaoma/p/9533018.html
- Vue + Element UI 实现权限管理系统 前端篇(七):功能组件封装
组件封装 为了避免组件代码的臃肿,这里对主要的功能部件进行封装,保证代码的模块化和简洁度. 组件结构 组件封装重构后,试图组件结构如下图所示 代码一览 Home组件被简化,包含导航.头部和主内容三个组 ...
- Vue + Element UI 实现权限管理系统 前端篇(十三):页面权限控制
权限控制方案 既然是后台权限管理系统,当然少不了权限控制啦,至于权限控制,前端方面当然就是对页面资源的访问和操作控制啦. 前端资源权限主要又分为两个部分,即导航菜单的查看权限和页面增删改操作按钮的操作 ...
- Vue + Element UI 实现权限管理系统 前端篇(十二):用户管理模块
用户管理模块 添加接口 在 http/moduls/user.js 中添加用户管理相关接口. import axios from '../axios' /* * 用户管理模块 */ // 保存 exp ...
- Vue + Element UI 实现权限管理系统 (管理应用状态)
使用 Vuex 管理应用状态 1. 引入背景 像先前我们是有导航菜单栏收缩和展开功能的,但是因为组件封装的原因,隐藏按钮在头部组件,而导航菜单在导航菜单组件,这样就涉及到了组件收缩状态的共享问题.收缩 ...
- Vue + Element UI 实现权限管理系统 前端篇(八):管理应用状态
使用 Vuex 管理应用状态 1. 引入背景 像先前我们是有导航菜单栏收缩和展开功能的,但是因为组件封装的原因,隐藏按钮在头部组件,而导航菜单在导航菜单组件,这样就涉及到了组件收缩状态的共享问题.收缩 ...
- Vue + Element UI 实现权限管理系统 前端篇(十一):第三方图标库
使用第三方图标库 用过Elment的同鞋都知道,Element UI提供的字体图符少之又少,实在是不够用啊,幸好现在有不少丰富的第三方图标库可用,引入也不会很麻烦. Font Awesome Font ...
- Vue + Element UI 实现权限管理系统(第三方图标库)
使用第三方图标库 用过Elment的同鞋都知道,Element UI提供的字体图符少之又少,实在是不够用啊,幸好现在有不少丰富的第三方图标库可用,引入也不会很麻烦. Font Awesome Font ...
- Vue + Element UI 实现权限管理系统 前端篇(十四):菜单功能实现
菜单功能实现 菜单接口封装 菜单管理是一个对菜单树结构的增删改查操作. 提供一个菜单查询接口,查询整颗菜单树形结构. http/modules/menu.js 添加 findMenuTree 接口. ...
随机推荐
- leecode第四题(寻找两个有序数组的中位数)
题解: class Solution { public: double findMedianSortedArrays(vector<int>& nums1, vector<i ...
- => js 中箭头函数使用总结
箭头函数感性认识 箭头函数 是在es6 中添加的一种规范 x => x * x 相当于 function(x){return x*x} 箭头函数相当于 匿名函数, 简化了函数的定义. 语言的发展 ...
- 新建ng工程
有问题多看官网文档https://www.angular.cn/guide/quickstart 1 在远程仓库建立 1个完全空的仓库,不要建立readme.MD ng cli创建时会创建readm ...
- MYSQL的常用函数(字符串函数)
ASCII(char)返回字符的ASCII码值 BIT_LENGTH(str)返回字符串的比特长度 CONCAT(s1,s2...,sn)将s1,s2...,sn连接成字符串 CONCAT_WS(se ...
- Codeforces 233 D - Table
D - Table 思路:dp 首先,第i列的个数肯定和第i - n列个数一样,假设[i - n + 1, i - 1] 之间的个数之和为x,那么第i列和第i-n列的个数应该是n - x 那么我们可以 ...
- ace后台管理系统扁平化框架
Bootstrap ACE后台管理界面模板(扁平化) 所属分类:后台模板 文件大小:1.22 MB 阅读:236697次 下载:55929次 来源:www.daimajiayuan.com 分享到:更 ...
- English trip V1 - 24. Accommodations Teacher:Maple Key: make suggestions 提出建议
In this lesson you will learn to make suggestions. 在本课程中,您将学习如何提出建议. 课上内容(Lesson) Which place would ...
- 20 Interesting WPF Projects on CodePlex
20 Interesting WPF Projects on CodePlex (Some for Silverlight too) Pete Brown - 22 November 2010 I ...
- NYOJ - 整数划分(四)
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=746 要求对一个n的整数插入m个乘号,求最大结果. 构造dp:dp[i][j]表示枚举至j ...
- HTML页面加载完毕后运行的js
Js方法:<script type=”text/javascript”> window.onload=function (){ var userName=”xiaoming”; alert ...