vue3 elementplus tabs切换实现
Tabs 标签页 | Element Plus
<template><!-- editableTabsValue 是当前tab 的 name --><el-tabsv-model="editableTabsValue"type="border-card"editable@edit="handleTabsEdit"><!-- 这个是标签面板 面板数据 遍历 editableTabs 渲染--><el-tab-panev-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 = newPathtab.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 = newTabNameeditableTabs.value.push(newtab)editableTabsValue.value = newTabName} else if (action === 'remove') {const tabs = editableTabs.valuelet 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 = activeNameeditableTabs.value = tabs.filter((tab) => tab.name !== targetName)}
}
</script>
<style>
.el-tabs__new-tab {margin-right: 20px;
}
</style>