Tabs 标签页 | Element Plus
<template>
<!-- editableTabsValue 是当前tab 的 name -->
<el-tabs
v-model="editableTabsValue"
type="border-card"
editable
@edit="handleTabsEdit"
>
<!-- 这个是标签面板 面板数据 遍历 editableTabs 渲染-->
<el-tab-pane
v-for="item in editableTabs"
:key="item.name"
:label="item.title"
:name="item.name"
>
<!-- 页面内容 采用这种写法 包裹 keep-alive 标签是 组件保持keep-alive -->
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</el-tab-pane>
</el-tabs>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import type { TabPaneName } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { watch } from 'vue'
const route = useRoute()
const router = useRouter()
const initTab = {
title: route.meta.title || 'New Tab',
name: '1',
url: route.fullPath,
}
// 使用对象张开运算符 复制 initTab 直接使用 inittab指向的是同一个对象
// editableTabs tabs 数据 是一个数组 里面是对象 每个对象是一个标签页
const editableTabs = ref([{ ...initTab }])
// tabindex 是最新标签 name 新标签为 tabIndex = tabIndex + 1
let tabIndex = editableTabs.value.length
// 当前的激活页 name
const editableTabsValue = ref(editableTabs.value[0].name)
// 监听 $route 对象的变化 如果路由发生变化 就更新 editableTabs 中的 url 和 title
watch(
() => route.fullPath,
(newPath) => {
editableTabs.value.forEach((tab) => {
if (tab.name === editableTabsValue.value) {
if (tab.url === newPath) {
return
}
tab.url = newPath
tab.title = route.meta.title || 'New Tab'
}
})
},
{ deep: true },
)
// 监听 editableTabsValue 的变化
//如果 editableTabsValue 变化了 就是切换了标签页 就更新路由到对应标签页
watch(
() => editableTabsValue.value,
(newValue) => {
editableTabs.value.forEach((tab) => {
if (tab.name === newValue) {
if (tab.url === route.fullPath) {
return
}
router.push(tab.url)
}
})
},
)
// 处理标签页的编辑事件
// targetName 是当前标签页的 name
const handleTabsEdit = (
targetName: TabPaneName | undefined,
action: 'remove' | 'add',
) => {
if (action === 'add') {
const newTabName = `${++tabIndex}`
const newtab = { ...initTab }
newtab.name = newTabName
editableTabs.value.push(newtab)
editableTabsValue.value = newTabName
} else if (action === 'remove') {
const tabs = editableTabs.value
let activeName = editableTabsValue.value
// 如果删除的是当前激活的标签页,需要找到下一个标签页作为新的激活页
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
const nextTab = tabs[index + 1] || tabs[index - 1]
if (nextTab) {
activeName = nextTab.name
}
}
})
}
editableTabsValue.value = activeName
editableTabs.value = tabs.filter((tab) => tab.name !== targetName)
}
}
</script>
<style>
.el-tabs__new-tab {
margin-right: 20px;
}
</style>