1.菜单渲染(el-menu)
<el-menu :default-active="String(activeNav)"
class="el-menu-vertical-demo"
@open="handleOpen"
background-color="#222d32"
text-color="#f4f5f5"
@close="handleClose"
:unique-opened="true"
router>
<el-submenu v-if="item.children"
:index="item.path"
v-for="item in menuData"
:key="item.key">
<template slot="title">
<i :class="item.icon"
class="iconfont"></i>
<span>{{item.name}}</span>
</template>
<el-menu-item :index="subItem.path"
v-for="subItem in item.children"
:key="subItem.key">
<i :class="subItem.icon"
class="iconfont"></i>
{{subItem.name}}</el-menu-item>
</el-submenu>
<el-menu-item v-else
:index="item.path"
:key="item.name">
<i :class="item.icon"
class="iconfont"></i>
<span slot="title">{{item.name}}</span>
</el-menu-item>
</el-menu>
2.vuex
使用vuex存储路径数据,方便el-menu和el-tabs访问
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
openTab: [
{
name: 'analysis',
title: '首页',
closable: false
}
],
activeIndex: ''
},
getters: {
},
mutations: {
add_tabs(state, data) {
if (state.openTab.some(item => item.title === data.title)) return
state.openTab.push(data);
},
delete_tabs(state, route) {
let index = 0;
for (let i of state.openTab) {
if (i.route === route) {
break;
}
index++;
}
state.openTab.splice(index, 1);
},
set_active_tabs(state, index) {
state.activeIndex = index;
}
},
actions: {},
modules: {}
});
3.el-tabs组件
<template>
<!-- 自定义 动态增删 tabs 搭配 menu -->
<div class="tab-menu">
<el-tabs
v-model="activeIndex"
@tab-remove="removeTab"
@tab-click="clickTab"
>
<el-tab-pane
:key="item.name"
v-for="item in openTab"
:label="item.title"
:name="item.name"
:closable="item.closable"
>
<div class="tab-menu-content">
<router-view></router-view>
</div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
export default {
name: 'MenuTabs',
data() {
return {
activeIndex: '/analysis',
openTab: [
{
title: '首页',
name: '/analysis',
closable: false
}
]
};
},
computed: {},
watch: {
$route(to, form) {
var flag = false;
// 当前页面菜单已打开
for (let i = 0; i < this.openTab.length; i++) {
if (to.path == this.openTab[i].name) {
this.activeIndex = this.openTab[i].name;
flag = true;
break;
}
}
// 打开新的页面
if (!flag) {
if (!to.meta.title) {
to.meta.title = '我的日程';
}
console.log(to.meta);
let obj = {
title: to.meta.title,
name: to.path,
closable: true
};
this.activeIndex = to.path;
this.openTab.push(obj);
}
}
},
created() {
const sessionTab = JSON.parse(window.sessionStorage.getItem('openTab')) || '';
if (sessionTab) {
if (sessionTab.openTab.length != 0 && sessionTab.openTabPath.length != 0) {
for (let i = 0; i < sessionTab.openTab.length; i++) {
this.openTab.push({
title: sessionTab.openTab[i].title,
name: sessionTab.openTab[i].name,
closable: true
});
}
this.activeIndex = sessionTab.currActiveTabs;
this.$router.push({ path: this.activeIndex });
}
}
},
mounted() {
// 监听页面加载前
window.addEventListener('beforeunload', e => {
sessionStorage.setItem(
'openTab',
JSON.stringify({
openTab: this.openTab.filter(
item => item.name != '/analysis'
),
openTabPath: this.openTab.filter(
item => item.name !== '/analysis'
),
currActiveTabs: this.activeIndex
})
);
});
},
methods: {
clickTab(tab) {
this.activeIndex = tab.paneName;
this.$router.push({ path: this.activeIndex });
},
removeTab(target) {
// 删除的是当前选中的页面
if (this.activeIndex === target) {
this.openTab.forEach((item, index) => {
if (item.name == target) {
let nextTab = item[index + 1] || item[index - 1];
if (nextTab) {
this.activeIndex = nextTab.name;
}
}
});
}
var i = 0;
this.openTab.forEach((item, index) => {
if (item.name == target) {
// eslint-disable-next-line no-return-assign
return (i = index);
}
});
this.openTab.splice(i, 1);
// 更新路由
this.$router.push({ path: this.openTab[this.openTab.length - 1].name });
}
}
};
</script>
<style lang="scss" scoped>
.tab-menu {
::v-deep .el-tabs__header {
background: #fff;
padding-left: 10px;
}
.tab-menu-content {
padding: 10px;
}
}
</style>