这里直接拆成组件就可以,用到仓库是因为新增功能是新页面点击保存需要把新增的这个标签页去掉 首先需要注意的是keep-alive缓存的话多层路由不支持,需要处理路由,缓存主要是keep-alive的include属性
tabs.vue
<template>
<div class="elp_tab_box">
<el-tabs
v-model="activeTab"
:value='$route.path'
type="card"
@tab-click="tabClick"
@tab-remove='tabRemove'
id="elp_tab"
>
<el-tab-pane
closable
v-for="item in $store.state.editableTabs"
:key="item.route"
:label="item.name"
:name="item.route"
/>
</el-tabs>
<el-dropdown >
<i id="elp_dropdown" class="el-icon-arrow-down"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="closeRightTabs">关闭左侧</el-dropdown-item>
<el-dropdown-item @click.native="closeLeftTabs">关闭右侧</el-dropdown-item>
<el-dropdown-item @click.native="closeOtherTabs">关闭其他</el-dropdown-item>
<el-dropdown-item @click.native="closeAllTabs">关闭全部</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<script>
export default {
data() {
return {
currentRouterName: "",
currentRouter: "",
activeTab: "",
editableTabs: [],
};
},
watch: {
$route: {
handler(to, form) {
this.activeTab = to.path
this.controlTabs(to);
if (to.query.type !== "0") {
let list = this.$store.state.editableTabs.map((item)=>item.title);
list.forEach((item, index) => {
if (item === to.name) {
list.splice(index, 1);
}
});
// this.alive=list.join(',')
this.$store.dispatch("setList", list);
}
else if(to.query.type === "0"){
let list = this.$store.state.editableTabs.map((item)=>item.title);
// this.alive=list.join(',')
this.$store.dispatch("setList", list);
}
this.$nextTick(()=>{
let list = this.$store.state.editableTabs.map((item)=>item.title);
this.$store.dispatch("setList", list);
})
console.log(this.$store.state.tabsList, "000000000000000");
},
immediate: true,
deep: true,
},
},
methods: {
controlTabs(route) {
var flag = false;
this.currentRouterName = route.meta.title;
this.currentRouter = route.path;
for (let item of this.editableTabs) {
if (item.route === route.path) {
this.activeTable = route.path;
flag = true;
break;
}
}
if (!flag) {
let names = route.meta.title;
if (names.indexOf("/", 1) != -1) {
names = names.substring(names.indexOf("/" + 1));
}
let param = {
route: route.path,
name: names,
title:route.name
};
this.editableTabs.push(param);
this.$store.dispatch('setEdit',this.editableTabs)
var arr= this.editableTabs.map((item)=>{
return item.title
})
this.$store.dispatch('setList',arr)
this.activeTab = route.path;
}
},
tabClick() {
this.$router.push({ path: this.activeTab, query:{type:'0'} });
},
tabRemove(targetName) {
if (this.activeTab === targetName) {
this.editableTabs.forEach((tab, index) => {
if (tab.route === targetName) {
let nextTab =
this.editableTabs[index + 1] || this.editableTabs[index - 1];
if (nextTab) {
this.$router.push({ path: nextTab.route ,query:{type:'0'}});
this.editableTabs.splice(index, 1);
this.$store.dispatch('setEdit',this.editableTabs)
var arr= this.editableTabs.map((item)=>{
return item.title
})
this.$store.dispatch('setList',arr)
}
}
});
} else {
this.editableTabs = this.editableTabs.filter((item) => {
if (item.route != targetName) {
return item;
}
});
this.$store.dispatch('setEdit',this.editableTabs)
var arr= this.editableTabs.map((item)=>{
return item.title
})
this.$store.dispatch('setList',arr)
}
},
closeRightTabs(){
const index=this.editableTabs.findIndex(item=>item.route==this.activeTab)
if(index!==-1){
this.editableTabs.splice(0,index)
this.$store.dispatch('setEdit',this.editableTabs)
var arr= this.editableTabs.map((item)=>{
return item.title
})
this.$store.dispatch('setList',arr)
}
},
closeLeftTabs(){
const index=this.editableTabs.findIndex(item=>item.route==this.activeTab)
if(index!==-1){
this.editableTabs.splice(index+1)
this.$store.dispatch('setEdit',this.editableTabs)
var arr= this.editableTabs.map((item)=>{
return item.title
})
this.$store.dispatch('setList',arr)
}
},
closeOtherTabs(){
this.editableTabs=this.editableTabs.filter(item=>item.route===this.activeTab)
this.$store.dispatch('setEdit',this.editableTabs)
var arr= this.editableTabs.map((item)=>{
return item.title
})
this.$store.dispatch('setList',arr)
},
closeAllTabs(){
this.activeTab=this.editableTabs[0].route
this.currentRouter=this.editableTabs[0].route
this.editableTabs=[this.editableTabs[0]]
this.$store.dispatch('setEdit',this.editableTabs)
var arr= this.editableTabs.map((item)=>{
return item.title
})
this.$store.dispatch('setList',arr)
this.$router.push({path:this.currentRouter,query:{type:'0'}})
console.log(this.editableTabs)
}
},
};
</script>
<style>
#elp_tab>.el-tabs__header .el-tabs__item .el-icon-close{
width: 12px !important;
}
#elp_tab>.el-tabs__header .el-tabs__item{
background: #fff !important;
margin: 8px 0 0 8px;
border-radius: 6px;
border: none;
}
#elp_tab .el-tabs__nav{
border: none !important;
/* margin-left: 8px; */
}
#elp_tab .el-tabs__header{
border-bottom: none !important;
}
#elp_tab .el-tabs__nav-prev{
margin-left: 8px;
line-height: 55px;
font-size: 16px;
}
#elp_tab{
width: 97%;
}
#elp_tab .el-tabs__nav-next{
margin-right: 8px;
margin-left: 20px;
line-height: 55px;
font-size: 16px;
}
#elp_tab .el-tabs__nav-scroll{
width: 99%;
margin-left: 8px;
}
#elp_dropdown{
display: inline-block;
padding: 5px;
background: #fff;
margin-right: 20px;
}
.elp_tab_box .el-dropdown{
line-height: 54px;
font-size: 21px;
}
.elp_tab_box{
display: flex;
justify-content: space-between;
}
</style>
index.vue
调用组件
<template>
<el-main class="elp-main">
<Tabs/>
<transition name="fade" mode="out-in">
<keep-alive :include="tabsList">
<router-view :key="$route.path"></router-view>
</keep-alive>
</transition>
</el-main>
</template>
<script>
import Tabs from '@/components/tabPane'
export default{
computed: {
tabsList(){
return this.$store.state.tabsList
},
},
}
</script>
仓库里的内容
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
editableTabs: [],
aliveList:[],
tabsList:'',
},
actions:{
setList({commit},payload){
commit('setTableList',payload)
},
setEdit({commit},payload){
commit('setEdittableTabs',payload)
}
},
mutations: {
setEdittableTabs(state,payload){
state.editableTabs=payload
},
setTableList(state,payload){
// this.dispatch('setList',payload)
state.aliveList=payload.map((item)=>{
return item
})
state.tabsList=state.aliveList.join(',')
}
},
})
router.js
这是路由的内容,需要注意name需要和.vue文件里的name一致,要不缓存不生效,title是你在缓存的标签页展示的内容
const routes=[ {
path: "/dataManagement",
name: "DataManagement",
component: () => import("../views/dataManagement/index.vue"),
children: [
{
path: 'storeManagement',
name: 'StoreManagement',
component: () => import("../views/dataManagement/storeManagement/index.vue"),
meta: {
title: '仓库管理'
},
// redirect: function() {
// return {name: 'mdmStore'}
// },
children: [
{
path: 'mdmStore',
name: 'mdmStore',
meta: {
title: 'MDM仓库管理'
},
component: () => import('../views/dataManagement/storeManagement/mdmStore/index.vue')
},
{
path: 'storeList',
name: 'storeList',
meta: {
title: '仓库管理'
},
component: () => import('../views/dataManagement/storeManagement/storeList')
},
// 新增仓库
{
path: 'storeList/addList',
name: 'addList',
component: () => import('../views/dataManagement/storeManagement/storeList/components/addList.vue')
},
]
}
}]
function handleKeepAlive(to) {
if (to.matched && to.matched.length > 2) {
for (let i = 0; i < to.matched.length; i++) {
const element = to.matched[i]
if (element.components.default.name === 'StoreManagement') {
to.matched.splice(i, 1)
}
}
}
}
//路由守卫
router.beforeEach((to, from, next) => {
handleKeepAlive(to)
next();
});