vue3+ts项目实现动态增减标签页跳转相应页面
时间: 2023-08-22 17:06:04 浏览: 189
好的,下面我来讲一下如何在 Vue3 + TypeScript 项目中实现动态增减标签页并跳转到相应页面的操作。
首先,在 Vue3 中实现动态标签页与上面的回答类似,需要创建一个 `tabs` 数组来存储标签页信息,并使用动态组件来加载对应的页面组件。
不过,在 TypeScript 中,我们需要对 `tabs` 数组进行类型定义。我们可以定义一个 `Tab` 接口来描述标签页的结构:
```typescript
interface Tab {
title: string;
path: string;
component: any; // 动态组件类型为 any
}
```
其中,`title` 表示标签页的标题,`path` 表示标签页跳转的路由路径,`component` 表示对应的页面组件,由于是动态加载的组件,因此类型为 `any`。
接着,在 Vue 组件中,我们需要使用 `ref` 来创建 `tabs` 和 `currentTab` 变量,并对其进行类型定义:
```typescript
import { defineComponent, ref } from 'vue';
export default defineComponent({
name: 'Tabs',
setup() {
const tabs = ref<Tab[]>([]);
const currentTab = ref<Tab>();
// ...
},
});
```
在此示例中,我们使用了泛型 `Tab[]` 来对 `tabs` 数组进行类型定义,并使用 `Tab` 对象对 `currentTab` 进行类型定义。
接下来,我们需要实现标签页增加、删除和跳转的逻辑。这里我们可以定义以下方法:
```typescript
const addTab = (tab: Tab) => {
const index = tabs.value.findIndex((item) => item.path === tab.path);
if (index === -1) {
tabs.value.push(tab);
currentTab.value = tab;
} else {
currentTab.value = tabs.value[index];
}
};
const removeTab = (tab: Tab) => {
const index = tabs.value.findIndex((item) => item.path === tab.path);
if (index !== -1) {
tabs.value.splice(index, 1);
if (currentTab.value === tab) {
currentTab.value = tabs.value[index] || tabs.value[index - 1];
}
}
};
const switchTab = (tab: Tab) => {
currentTab.value = tab;
};
```
其中,`addTab` 方法用于增加一个标签页,如果 `tabs` 数组中不存在对应的标签页,则新增一个标签页,并将 `currentTab` 设置为新增的标签页;否则直接将 `currentTab` 设置为已存在的标签页。
`removeTab` 方法用于删除一个标签页,如果 `tabs` 数组中存在对应的标签页,则从 `tabs` 数组中移除该标签页,并将 `currentTab` 设置为上一个或下一个标签页(如果当前标签页是第一个或最后一个标签页,则将 `currentTab` 设置为上一个或下一个标签页,否则将 `currentTab` 设置为第一个标签页)。
`switchTab` 方法用于切换到指定的标签页,将 `currentTab` 设置为指定的标签页。
最后,在模板中,我们可以使用 `v-for` 循环渲染 `tabs` 数组,并使用 `router-link` 实现标签页跳转:
```html
<template>
<div class="tabs">
<ul>
<li v-for="tab in tabs" :key="tab.path" :class="{ active: currentTab === tab }">
<router-link :to="tab.path" exact @click.native="switchTab(tab)">{{ tab.title }}</router-link>
<span class="close" @click="removeTab(tab)">x</span>
</li>
</ul>
<router-view />
</div>
</template>
```
在此模板中,我们使用 `v-for` 循环渲染 `tabs` 数组,并使用 `router-link` 实现标签页跳转。在点击 `router-link` 时,我们调用 `switchTab` 方法切换到对应的标签页,并设置 `router-link` 的 `exact` 属性,使得在当前标签页时,`router-link` 也能被激活。
完整的代码如下:
```typescript
<template>
<div class="tabs">
<ul>
<li v-for="tab in tabs" :key="tab.path" :class="{ active: currentTab === tab }">
<router-link :to="tab.path" exact @click.native="switchTab(tab)">{{ tab.title }}</router-link>
<span class="close" @click="removeTab(tab)">x</span>
</li>
</ul>
<router-view />
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { RouteRecordRaw, useRoute, useRouter } from 'vue-router';
interface Tab {
title: string;
path: string;
component: any;
}
export default defineComponent({
name: 'Tabs',
setup() {
const tabs = ref<Tab[]>([]);
const currentTab = ref<Tab>();
const route = useRoute();
const router = useRouter();
const addTab = (tab: Tab) => {
const index = tabs.value.findIndex((item) => item.path === tab.path);
if (index === -1) {
tabs.value.push(tab);
currentTab.value = tab;
} else {
currentTab.value = tabs.value[index];
}
};
const removeTab = (tab: Tab) => {
const index = tabs.value.findIndex((item) => item.path === tab.path);
if (index !== -1) {
tabs.value.splice(index, 1);
if (currentTab.value === tab) {
currentTab.value = tabs.value[index] || tabs.value[index - 1];
}
}
};
const switchTab = (tab: Tab) => {
currentTab.value = tab;
router.push(tab.path);
};
const findTabByPath = (path: string) => {
return tabs.value.find((tab) => tab.path === path);
};
const createRouteTabs = (routes: RouteRecordRaw[]) => {
routes.forEach((route) => {
if (route.meta?.showInTabs) {
addTab({
title: route.meta.title || route.name || '',
path: route.path,
component: route.component || {},
});
}
if (route.children) {
createRouteTabs(route.children);
}
});
};
createRouteTabs(router.getRoutes());
const created = () => {
const tab = findTabByPath(route.path);
if (tab) {
currentTab.value = tab;
} else {
const { meta, name, path, component } = route;
addTab({
title: meta.title || name || '',
path,
component: component || {},
});
}
};
return {
tabs,
currentTab,
addTab,
removeTab,
switchTab,
created,
};
},
});
</script>
```
在此示例中,我们还使用了 `useRoute` 和 `useRouter` 钩子来获取当前路由信息和路由实例,从而实现了在页面刷新时恢复标签页状态的功能。同时,我们也通过 `meta` 字段来标记哪些路由需要在标签页中显示。
阅读全文