目标:左侧导航区 右侧为展示区 点击导航区的某一项 右侧会新建一个标签页 展示内容 标签页之间可以点击切换 可以关闭除首页的其他标签页
目的效果如图
<el-main style="background-color: #ecf5ff;">
<Tab></Tab>
<RouterView></RouterView>
</el-main>
以下为Tab.vue 思路就是标签页的组件记录路由的path 被选中就将对应的path push到路由器里 将<RouteView/>的内容替换
<template>
<el-tabs v-model="activeTab" @tab-change="tabChange" @tab-remove="tabRemove">
<el-tab-pane v-for="item in tabList" :key="item.path" :label="item.title" :name="item.path"
:closable="item.path != '/'">
</el-tab-pane>
</el-tabs>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue'
import { useRoute, useRouter } from 'vue-router';
interface TabType {
'title': string,
'path': string
}
const route = useRoute()
const router = useRouter()
const activeTab = ref(route.path)
const tabList = reactive([
{
title: '首页',
path: '/'
}
])
//点击标签导致activeTab改变时触发
function tabChange(tab: string) {
console.log('tabChange')
router.push(tab)
activeTab.value = tab
}
//添加路由 添加到标签页
function addTab(tab: TabType) {
const index = tabList.findIndex((item) => item.path == tab.path)
//选中的菜单项目前没有在标签页中 需要添加到标签页中
if (index == -1) {
tabList.push(tab)
}
}
//点击菜单导致路由变化 路由变化之前使用这个全局守卫
router.beforeEach((to) => {
activeTab.value = to.path
addTab({
title: to.meta.title as string,
path: to.path
})
})
function tabRemove(targetTab: string) {
let targetIndex: number = 0 //要关闭的tab的index
//先找到要删除的
tabList.forEach((tab, index) => {
if (tab.path == targetTab) {
targetIndex = index
}
})
//要关闭的是当前活跃的tab
if (activeTab.value == targetTab) {
const nextTab = tabList[targetIndex - 1] || tabList[targetIndex + 1]
activeTab.value = nextTab.path
router.push(activeTab.value)
}
tabList.splice(targetIndex, 1)
}
</script>
以下为route/index.ts
import { createRouter, createWebHistory } from "vue-router";
import CmTrendCodeList from "@/views/CmTrendCodeList.vue";
import LeaseList from "@/views/Lease/LeaseList.vue";
import Home from '@/views/Home.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/CmTrendCode',
component: CmTrendCodeList,
meta: {
title: '动态代码'
}
},
{
path: '/LeaseList',
component: LeaseList,
meta: {
title: '租箱协议'
}
},
{
path: '/',
component: Home,
meta: {
title: '首页'
}
}
]
})
export default router
参考了https://blog.csdn.net/samate6666/article/details/126950343
但不同的是 我使用的是router.beforeEach()这个全局前置守卫 而不是onBeforeRouterUpdate() 我个人理解是onBeforeRouteUpdate()、beforeRouteUpdate()这些是组件内守卫 需要在组件内使用 就是到时候去替换<RouteView/>的那些组件 不然会有警告:App.vue:13 [Vue Router warn]: No active route record was found when calling `onBeforeRouteUpdate()`. Make sure you call this function inside a component child of <router-view>. Maybe you called it inside of App.vue?
被这个问题折磨了很久 去看了以下官方文档 发现onBeforeRouteUpdate()不能解决我的问题 也可能是我菜 觉得beforeEach()挺合适 如果觉得有帮助点个赞趴 谢谢