components
myHeader.vue
<template>
<div class="my-header">
<!-- 布局,一行 -->
<el-row>
<!-- 布局,占12列 -->
<el-col :span="12" class="header-title">
<!-- 系统标题,文字类,未使用图标形式,可以在这里替换 -->
<h1>学生成绩管理系统</h1>
</el-col>
<!-- 布局,占2列,右位移10列 -->
<el-col :span="2" :offset="10" class="user-info">
用户 : <span class="user-name">{{userInfo.userName}}</span>
</el-col>
</el-row>
</div>
</template>
<script>
import { mapGetters } from 'vuex' //引入vuex函数
export default {
name: "MyHeader",
computed: {
//计算属性,自动获取vuex中的用户信息
...mapGetters(['userInfo'])
}
}
</script>
<style lang="scss" scoped>
.my-header{
.header-title{
line-height: 60px;
font-family: 华文彩云,Arial,Sans-serif,serif;
font-weight: bold;
font-size: 23px;
}
.user-info{
text-align: center;
line-height: 60px;
.user-name{
padding-left: 5px;
color: red;
font-weight: bold;
}
}
}
</style>
sidebar.vue
<template>
<div class="sidebar">
<!-- 菜单顶部,折叠按钮 -->
<div class="sidebar-collapse">
<!-- 折叠时,》,展开时 《 -->
<span
@click="toggleCollapse"
:class="isCollapsed ? 'el-icon-d-arrow-right' : 'el-icon-d-arrow-left'">
</span>
</div>
<!-- 菜单 -->
<!--
default-active默认激活
collapse折叠
collapse-transtion折叠时动画
background-color背景色
text-color文字颜色
active-text-color激活项文字颜色
router开启配合路由
-->
<el-menu
:default-active="activeName"
class="el-menu-vertical-demo"
:collapse="isCollapsed"
:collapse-transition="false"
background-color="#003c7f"
text-color="#fff"
active-text-color="#ffd04b"
router>
<!--
v-for循环
index访问路由路径
key索引
class图标
-->
<el-menu-item
:index="item.path"
v-for="item in menuList"
:key="item.path">
<i :class="item.iconName"></i>
<span slot="title">{{item.menuName}}</span>
</el-menu-item>
<!-- 退出, -->
<el-menu-item index="logout" @click="logout">
<i class="el-icon-unlock"></i>
<span slot="title">退出</span>
</el-menu-item>
</el-menu>
</div>
</template>
<script>
import menuList from "@/config/MenuList"; //引入模拟动态菜单
import {clearAll} from "@/storage"; //引入本地储存的函数
export default {
name: "SideBar",
data(){
return {
//菜单是否折叠
isCollapsed: false,
//菜单数组
menuList: menuList,
}
},
computed:{
//当前激活的菜单名
activeName(){
return this.$router.path;
}
},
methods: {
//退出
logout(){
//提示框
this.$confirm('您确定要退出系统吗?',"提示",{
confirmButtonText:'退出',
cancelButtonText: '取消',
type:'warning'
}).then(()=> {
//清除vuex,清除本地存储,清除token
this.$store.dispatch('clearAll');
//提示
this.$message.success('退出成功');
//路由跳转
this.$router.replace('/');
}).catch(_=> {
//取消,提示
this.$message.warning('已取消退出');
//因退出的路由是假路由,修复bug,切换回主页
this.$router.push('/index');
})
},
toggleCollapse(){
//修改父级中的asideWidth
if(this.isCollapsed){
//展开
this.$emit('changeWidth','200px');
} else {
//折叠
this.$emit('changeWidth','65px');
}
//折叠,展开,自动切换
this.isCollapsed = !this.isCollapsed;
}
}
}
</script>
<style lang="scss" scoped>
.sidebar{
.sidebar-collapse{
background-color: rgb(110,170,220);
padding: 8px;
color: #ffffff;
text-align: center;
cursor: pointer;
line-height: 1.5;
span{
width: 100%;
}
}
/*
避免选中时,出现右侧1px的超出
*/
.el-menu{
border-right-width: 0;
}
}
</style>
tabview.vue
<template>
<div>
<!-- :value是当前激活状态的页,根据当前路由路径 -->
<el-tabs :value="activeName" @tab-remove="removeTab" @tab-click="tabClick">
<!--
v-for循环
key是索引
label是页签标题
name是路由
closable是开启可关闭按钮的 ,首页不可关闭
-->
<el-tab-pane
v-for="item in openedTabs"
:key="item.path"
:label="item.text"
:name="item.path"
:closable = "item.path !== '/index'">
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
export default {
name: "TabView",
props: {
//父传子,接收已打开的页签数组
"openedTabs":{
type: Array, //类型,数组
required: true //必填
}
},
computed:{
//计算属性
activeName(){
//返回当前路由
return this.$route.path;
}
},
methods: {
//页签点击时,回显内容
tabClick(tab){
//修复bug,处在当前页,再点击当前页,出现死循环bug
if(this.$router.currentRoute.path === tab.name) return;
//先查找点击页签,
let currentTab = this.openedTabs.find(item => item.path === tab.name);
//在跳转页签对应的路由
this.$router.replace(currentTab.fullPath);
},
//关闭页签tab
removeTab(tabName) {
//判断是否关闭的是当前页
if(tabName !== this.activeName){
//不是当前页的,直接关闭
this.$store.dispatch('closeTab',tabName);
return
}
//关闭激活的当前页
//先找当前页索引
let tabIndex = this.openedTabs.findIndex(item => item.path === tabName);
//再找当前页索引左侧的页签tab
let tabToActive = this.openedTabs[tabIndex -1];
//切换当前页
this.$router.replace(tabToActive.fullPath);
//关闭当前页
this.$store.dispatch('closeTab',tabName);
}
},
//监听
watch: {
//新增tab
$route: {
//立即
immediate: true,
//处理函数
handler(newValue,oldValue){
let tab = {
path: newValue.path, //页签路径
text: newValue.meta.title, //页签标题
fullPath: newValue.fullPath, //页签全路径,带参数
};
//调用vuex,保存页签
this.$store.dispatch('addTab',tab);
}
}
}
}
</script>
<style scoped>
</style>