效果如下:
el-header,el-aside,el-main布局,el-main中
<el-main>
<el-tabs v-model="editableTabsValue" type="card" @tab-remove="removeTab" @tab-click="tabClick">
<el-tab-pane
v-for="(item, index) in editableTabs"
:key="item.name"
:label="item.title"
:name="item.name"
:closable="item.closable"
>
</el-tab-pane>
</el-tabs>
<keep-alive>
<router-view></router-view>
</keep-alive>
</el-main>
router-view 用来跳转路由,调用data如下
data() {
return {
activeIndex: '1',
isCollapse: false,
styleimg: 'fa fa-outdent',
menulist: [],
editableTabsValue: 'home',//tab选中name
editableTabs: [],//tab数据
}
}
点击左侧菜单新增tab,menunametab名称,url为name,新增判断是否存在已经有的tab,
data中 editableTabsValue,editableTabs,都是取vuex里面设置的,后面贴代码
created() {
//验证是否登录
this.verification()
//树形菜单
this.getMenu()
//初始化tab
this.editableTabs = this.$store.state.options
//网址进入选中tab
this.initeditableTabsValue()
}
//新增tab
addTab(menuName,url) {
let tabs = this.editableTabs;
var isExist =false
tabs.forEach((tab, index) => {
if (tab.name === url) {
isExist =true
}
})
if (isExist){
this.$store.commit('set_active_index', url)
this.editableTabsValue =this.$store.state.activeIndex
}
else{
this.$store.commit('add_tabs', {
title: menuName,
name: url,
closable:true,
})
this.$store.commit('set_active_index', url)
this.editableTabsValue =this.$store.state.activeIndex
}
},
删除tab,移除vuex数据
//删除tab
removeTab(targetName) {
this.$store.commit('delete_tabs', targetName)
this.$store.commit('set_active_index', 'home')
},
tab点击
//tab点击
tabClick(targetName){
console.log(targetName)
this.$store.commit('set_active_index', targetName.name)
this.$router.push({path:'/'+targetName.name})
},
输入网址,进入选中tab
//初始化tab加载选择
initeditableTabsValue(){
let url = this.$route.fullPath.replace('/','')
let tabs = this.editableTabs;
let isExist =false
tabs.forEach((tab, index) => {
if (tab.name === url) {
isExist =true
}
})
if (isExist){
this.$store.commit('set_active_index', url)
this.editableTabsValue =this.$store.state.activeIndex
}else{
this.$store.commit('set_active_index', 'home')
this.editableTabsValue =this.$store.state.activeIndex
}
},
具体代码如下:
1.调用Vuex,index.js,options为editableTabs数据,写死一条主页tab,根据自己需要,这里vuex
actions,mutations,getters,modules分开了
import Vue from 'vue'
import Vuex from 'vuex'
import actions from "@/store/actions";
import mutations from "@/store/mutations";
import getters from "@/store/getters";
import modules from "@/store/modules";
Vue.use(Vuex)
const state = sessionStorage.getItem('state') ? JSON.parse(sessionStorage.getItem('state')) : {
token: "",
options: [{
title: '主页',
name: 'home',
closable:false
}],
activeIndex: 'home'
}
export default new Vuex.Store({
state,
mutations,
actions,
getters,
modules
})
2.mutations.js
export default {
//添加token
mGetToken(state, payload) {
this.state.token = payload
},
// 添加tabs
add_tabs (state, data) {
this.state.options.push(data);
},
// 删除tabs
delete_tabs (state, route) {
let index = 0;
for (let option of state.options) {
if (option.name === route) {
break;
}
index++;
}
this.state.options.splice(index, 1);
},
// 设置当前激活的tab
set_active_index (state, index) {
this.state.activeIndex = index;
}
}
3.vue页面
<template>
<div>
<el-container class="home-container">
<el-header>
<el-row>
<el-col :span="1" style="height: 60px"><a href="home"><img src="https://img01.yzcdn.cn/vant/logo.png" alt=""></a></el-col>
<el-col :span="6"><a href="home"><div class="home-main">后台管理系统</div></a></el-col>
<el-col :span="12">
<el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect"
background-color="#4a90e2"
text-color="#fff"
active-text-color="#ffd04b">
<el-menu-item index="1">业绩考评</el-menu-item>
<el-menu-item index="2">工作成效</el-menu-item>
<el-menu-item index="3">个人中心</el-menu-item>
</el-menu>
</el-col>
<el-col :span="5">
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">系统管理员
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item icon="fa fa-edit" command="修改密码">修改密码</el-dropdown-item>
<el-dropdown-item icon="fa fa-upload" command="上传头像">上传头像</el-dropdown-item>
<el-dropdown-item icon="fa fa-sign-out" divided command="退出系统">退出系统</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
</el-row>
</el-header>
<el-container>
<el-aside :width="isCollapse?'64px':'200px'">
<div @click="activeCollapse">
<span :class="styleimg" style="text-align: center;font-size: 16px;line-height: 30px;width: 100%;color: #909399;padding-right: 2px"></span>
</div>
<el-divider></el-divider>
<el-menu
:collapse="isCollapse"
unique-opened
:collapse-transition="false"
router
background-color="#336699"
text-color="#fff"
active-text-color="#FF9900">
<el-submenu :index="mainitem.Menuid" v-for="mainitem in menulist":key="mainitem.Menuid">
<template slot="title">
<i :class="mainitem.Icon" style="margin-right: 8px;font-size:16px"></i>
<span>{{mainitem.Menuname}}</span>
</template>
<el-menu-item :index="item.Url" v-for=" item in mainitem.children" :key="item.Menuid" @click="addTab(item.Menuname,item.Url)">
<template slot="title">
<i :class="item.Icon" style="margin-right: 8px;font-size:16px"></i>
<span>{{item.Menuname}}</span>
</template>
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-main>
<el-tabs v-model="editableTabsValue" type="card" @tab-remove="removeTab" @tab-click="tabClick">
<el-tab-pane
v-for="(item, index) in editableTabs"
:key="item.name"
:label="item.title"
:name="item.name"
:closable="item.closable"
>
</el-tab-pane>
</el-tabs>
<keep-alive>
<router-view></router-view>
</keep-alive>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import {GetUserMenu} from "@/network/user";
export default {
name: "Main",
created() {
//验证是否登录
this.verification()
//树形菜单
this.getMenu()
//初始化tab
this.editableTabs = this.$store.state.options
//网址进入选中tab
this.initeditableTabsValue()
},
data() {
return {
activeIndex: '1',
isCollapse: false,
styleimg: 'fa fa-outdent',
menulist: [],
editableTabsValue: 'home',//tab选中name
editableTabs: [],//tab数据
}
},
methods:{
//新增tab
addTab(menuName,url) {
let tabs = this.editableTabs;
var isExist =false
tabs.forEach((tab, index) => {
if (tab.name === url) {
isExist =true
}
})
if (isExist){
this.$store.commit('set_active_index', url)
this.editableTabsValue =this.$store.state.activeIndex
}
else{
this.$store.commit('add_tabs', {
title: menuName,
name: url,
closable:true,
})
this.$store.commit('set_active_index', url)
this.editableTabsValue =this.$store.state.activeIndex
}
},
//删除tab
removeTab(targetName) {
this.$store.commit('delete_tabs', targetName)
this.$store.commit('set_active_index', 'home')
},
//tab点击
tabClick(targetName){
console.log(targetName)
this.$store.commit('set_active_index', targetName.name)
this.$router.push({path:'/'+targetName.name})
},
verification() {
if (this.$store.state.token == '') {
this.$router.push({path: '/login'})
}
},
handleCommand(command){
if (command == '退出系统'){
window.sessionStorage.removeItem('state')
this.$store.commit('mGetToken', '')
//移除option
let tabs = this.$store.state.options;
let deletelist =''
tabs.forEach((tab, index) => {
console.log(index)
if (tab.name !== 'home') {
deletelist+=tab.name+','
}
})
deletelist = deletelist.substring(0,sj.length-1)
let list = deletelist.split(',')
list.forEach((c, index) => {
this.$store.commit('delete_tabs', c)
})
this.$store.commit('set_active_index', 'home')
this.$router.push({path: '/login'})
}
},
handleSelect(key, keyPath){
console.log(key, keyPath);
},
activeCollapse(){
this.isCollapse=!this.isCollapse
this.styleimg = this.isCollapse===true?'fa fa-indent':'fa fa-outdent'
},
getMenu(){
GetUserMenu(this.$store.state.token).then(res => {
this.menulist =res.data
}).catch(err => {
console.log(err);
})
},
//初始化tab加载选择
initeditableTabsValue(){
let url = this.$route.fullPath.replace('/','')
let tabs = this.editableTabs;
let isExist =false
tabs.forEach((tab, index) => {
if (tab.name === url) {
isExist =true
}
})
if (isExist){
this.$store.commit('set_active_index', url)
this.editableTabsValue =this.$store.state.activeIndex
}else{
this.$store.commit('set_active_index', 'home')
this.editableTabsValue =this.$store.state.activeIndex
}
},
},
}
</script>
<style scoped>
.el-header{
background-color: #4a90e2;
line-height: 60px;
}
home-header{
height: 60px;
}
.el-row{
height: 60px;
line-height: 60px;
}
.el-col img{
height: 60px;
}
.home-main{
font-weight: bold;
font-size: 30px;
font-family: 楷体;
color: white;
padding-left: 5px;
}
.el-aside {
background-color: #336699;
}
.el-menu {
border-right: none;
}
.el-main {
background-color: #ffffff;
}
.home-container {
height: 100vh;
}
.el-dropdown {
color: white;
float: right;
}
.el-menu-demo{
float: right;
}
.asidecollapse{
text-align: center;
}
.el-divider{
margin: 0 0;
background-color: #909399;
}
</style>