1.效果图
2.技术栈
借助elementUI组件库的tabs组件,结合路由对象,实现点击导航栏,增加tab栏,同时tab栏可删除的效果。
3.实现思路
- 封装tabs栏组件
<el-tabs
v-model="activeTabName"
type="card"
:closable="tabsTitle.length !== 1"
@tab-remove="removeTab"
@tab-click="tabClick"
>
<el-tab-pane
v-for="item in tabsTitle"
:key="item.name"
:label="item.title"
:name="item.name"
/>
</el-tabs>
- 计算属性获取所有路由信息
computed: {
routes() {
return this.$router.options.routes.filter(value => !value.hidden) // 获取所有的路由信息,并过滤掉不需要显示的路由(带有hidden属性)
}
},
- 侦听器监听$route的变化,增加tab栏并去重
watch: {
$route: {
async handler(to, from) {
// 获取当前要去向的路由对象
let obj = {}
this.routes.forEach(item => {
if (item.path === to.path || item.redirect === to.path) {
obj = item
} else if (item.children && item.children.length > 0) {
item.children.forEach(value => {
if (value.name === to.name) {
obj = value
}
})
}
})
this.tabsTitle.push({
title: (obj.meta && obj.meta.title) || obj.children[0].meta.title,
name: to.path
}) // 将当前路由对象中的path和meta.title以对象形式保存到tabsTitle中,供后续使用
this.activeTabName = to.path // 设置当前高亮tab栏
const strings = this.tabsTitle.map(item => JSON.stringify(item))
const removeDulpList = Array.from(new Set(strings))
this.tabsTitle = removeDulpList.map(item => JSON.parse(item)) // 上述操作对tabsTitle数组进行深度去重
},
deep: true, // 深度监听
immediate: true // 实时监听
}
},
- 删除tab栏功能
removeTab(removeName) {
const index = this.tabsTitle.findIndex(item => item.name === removeName) // 获取index
this.tabsTitle.splice(index, 1) // 删除点击tab移出按钮的tab栏
if (removeName === this.activeTabName) {
// 删除的tab栏是当前高亮的tab栏的情况
if (index === 0) {
// 如果的点击tab移出按钮的tab栏索引为0,则设置第0项tab栏为高亮
this.activeTabName = this.tabsTitle[index].name
} else {
// 设置index - 1项为高亮
this.activeTabName = this.tabsTitle[index - 1].name
}
// 跳转到高亮的tab栏
this.$router.push(this.activeTabName)
}
}
- 点击tab栏切换页面
tabClick(tab) {
this.$router.push(tab.name)
}
- 使用组件
<template>
<section class="app-main">
<tabs />
<transition name="fade-transform" mode="out-in">
<keep-alive>
<router-view :key="key" />
</keep-alive>
</transition>
</section>
</template>