[TOC]
## tabs组件
在`src/layouts/TabsView.vue`新建多页签组件,找到官网`tabs`组件
```
<template>
<div>
<div :style="{ marginBottom: '16px' }">
<a-button @click="add">
ADD
</a-button>
</div>
<a-tabs v-model="activeKey" hide-add type="editable-card" @edit="onEdit">
<a-tab-pane v-for="pane in panes" :key="pane.key" :tab="pane.title" :closable="pane.closable">
{{ pane.content }}
</a-tab-pane>
</a-tabs>
</div>
</template>
<script>
export default {
data() {
const panes = [
{ title: 'Tab 1', content: 'Content of Tab 1', key: '1' },
{ title: 'Tab 2', content: 'Content of Tab 2', key: '2' },
];
return {
activeKey: panes[0].key,
panes,
newTabIndex: 0,
};
},
methods: {
callback(key) {
console.log(key);
},
onEdit(targetKey, action) {
this[action](targetKey);
},
add() {
const panes = this.panes;
const activeKey = `newTab${this.newTabIndex++}`;
panes.push({
title: `New Tab ${activeKey}`,
content: `Content of new Tab ${activeKey}`,
key: activeKey,
});
this.panes = panes;
this.activeKey = activeKey;
},
remove(targetKey) {
let activeKey = this.activeKey;
let lastIndex;
this.panes.forEach((pane, i) => {
if (pane.key === targetKey) {
lastIndex = i - 1;
}
});
const panes = this.panes.filter(pane => pane.key !== targetKey);
if (panes.length && activeKey === targetKey) {
if (lastIndex >= 0) {
activeKey = panes[lastIndex].key;
} else {
activeKey = panes[0].key;
}
}
this.panes = panes;
this.activeKey = activeKey;
},
},
};
</script>
```
去掉add功能,修改代码
```
<template>
<a-tabs v-model="activePage" type="editable-card" :hide-add="true" @edit="editPage">
<!-- edit 新增和删除页签的回调,在 type="editable-card" 时有效 -->
<a-tab-pane v-for="page in pageList" :key="page.fullPath">
<span slot="tab" :pagekey="page.fullPath">{{ page.meta.title }}</span>
</a-tab-pane>
</a-tabs>
</template>
<script>
export default {
data() {
return {
activePage: "",
pageList: [], // 页签的路由数组
};
},
created() {
const route = this.$route;
this.pageList.push(route);
this.activePage = route.fullPath;
},
watch: {
$route: function (newRoute) {
// 当前路由高亮
this.activePage = newRoute.fullPath;
// 当前路由在页签中不存在时添加新页签
if (this.pageList.findIndex(item => item.fullPath == newRoute.fullPath) == -1) {
this.pageList.push(newRoute);
}
}
},
methods: {
callback(key) {
console.log(key);
},
editPage(key, action) {
this[action](key); // remove
},
remove(key, next) {
// 页签只有一个时 不能关闭
if (this.pageList.length === 1) {
return this.$message.warning("这是最后一页,不能再关闭了");
}
// 当前页签的索引
let index = this.pageList.findIndex(item => item.fullPath === key);
// 删除当前页签
this.pageList.splice(index, 1);
if (next) {
this.$router.push(next);
} else if (key === this.activePage) {
index = index >= this.pageList.length ? this.pageList.length - 1 : index;
this.activePage = this.pageList[index].fullPath;
this.$router.push(this.activePage);
}
},
}
};
</script>
```
在BasicLayout.vue中引入
```
<a-layout-content style="margin: 0 16px">
<!-- <router-view></router-view> -->
<tabs-view></tabs-view>
</a-layout-content>
```
## CustomEvent自定义页签关闭事件
用法
```
// 添加一个适当的事件监听器
obj.addEventListener("cat", function(e) { process(e.detail) })
// 创建并分发事件
var event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}})
obj.dispatchEvent(event)
```
新建`src/plugins/tabs-page-plugin.js`
```
const TabsPagePlugin = {
install(Vue) {
Vue.mixin({
methods: {
$closePage(closeRoute, nextRoute) {
// CustomEvent() 创建一个自定义事件
// CustomEvent.detail 只读 任何时间初始化时传入的数据
const event = new CustomEvent("page:close", { detail: { closeRoute, nextRoute } });
window.dispatchEvent(event);
}
}
});
}
};
export default TabsPagePlugin;
```
新建`src/plugins/index.js`,引入`TabsPagePlugin`
```
import TabsPagePlugin from "./tabs-page-plugin";
const Plugins = {
install: function (Vue) {
Vue.use(TabsPagePlugin);
}
};
export default Plugins;
```
`main.js`引入
```
import Plugins from "@/plugins";
Vue.use(Plugins);
```
修改`src/layouts/TabsView.vue`
```
<template>
<a-tabs v-model="activePage" type="editable-card" :hide-add="true" @edit="editPage">
<!-- edit 新增和删除页签的回调,在 type="editable-card" 时有效 -->
<a-tab-pane v-for="page in pageList" :key="page.fullPath">
<span slot="tab" :pagekey="page.fullPath">{{ page.meta.title }}</span>
</a-tab-pane>
</a-tabs>
<div class="tabs-view-content">
<keep-alive>
<router-view :key="$route.fullPath" ref="tabContent"/>
</keep-alive>
</div>
</template>
<script>
export default {
data() {
return {
activePage: "",
pageList: [], // 页签的路由数组
};
},
created() {
const route = this.$route;
this.pageList.push(route);
this.activePage = route.fullPath;
// 自定义监听关闭事件
window.addEventListener("page:close", this.closePageListener);
},
beforeDestroy() {
window.removeEventListener("page:close", this.closePageListener);
},
watch: {
$route: function (newRoute) {
// 当前路由高亮
this.activePage = newRoute.fullPath;
// 当前路由在页签中不存在时添加新页签
if (this.pageList.findIndex(item => item.fullPath == newRoute.fullPath) == -1) {
this.pageList.push(newRoute);
}
}
},
methods: {
callback(key) {
console.log(key);
},
editPage(key, action) {
this[action](key); // remove
},
remove(key, next) {
// 页签只有一个时 不能关闭
if (this.pageList.length === 1) {
return this.$message.warning("这是最后一页,不能再关闭了");
}
// 当前页签的索引
let index = this.pageList.findIndex(item => item.fullPath === key);
// 删除当前页签
this.pageList.splice(index, 1);
if (next) {
this.$router.push(next);
} else if (key === this.activePage) {
index = index >= this.pageList.length ? this.pageList.length - 1 : index;
this.activePage = this.pageList[index].fullPath;
this.$router.push(this.activePage);
}
},
closePageListener(event) {
const { closeRoute, nextRoute } = event.detail;
const closePath = typeof closeRoute === "string" ? closeRoute : closeRoute.path;
this.remove(closePath, nextRoute);
}
}
};
</script>
```
## 使用
关闭当前页面:`this.$closePage(this.$route.fullPath);`