在vue单页面应用中,当点击导航菜单时会切换路由,一般是在中间的router-view
路由视图中直接显示对应路由的页面组件,那么本编就介绍一下如何使用vue路由配合tab
组件实现多页签功能,打开一个新的菜单路由时变成弹出一个新的tab页签,并且随时可以切换到之前的页面,保留之前的组件状态。
当前打开的tab需要在data
中以一个数组的方式维护(openTab)
,默认显示首页
main.vue:
openTab: [
{
title: "首页",
name: "/Index", //路由
closable: false, //首页不可关闭
componentName: "index" //组件名称用于keepalive缓存
}
],
componentName
是对应tab中页面组件的name
值,所以每一个组件都必须设置自己的name值。
下面看template
如何实现,首先加入elementUI
的tab
组件:
<div
id="main-home"
>
<el-tabs
@tab-remove="removeTab"
v-model="activeIndex"
type="card"
class="main-tab"
@tab-click="clickTab"
>
<el-tab-pane
:key="item.name"
v-for="item in openTab"
:label="item.title"
:name="item.name"
:closable="item.closable"
></el-tab-pane>
</el-tabs>
<div class="view-container">
<keep-alive :include="openTab.map(i => i.componentName)">
<router-view v-if="isRouterAlive"></router-view>
</keep-alive>
</div>
</div>
注意router-view并没有放在el-tab-pane
中,而是抽到了外面,tab共用这一块试图,因为如果使用了多试图的方式会出现元素id属性可能相同的问题。同时使用keep-alive
缓存组件的状态。
可以使用include
存储当前tab的组件名name列表实现tab视图的缓存,这样互相切换就不需要重新加载组件,但是要特别注意组件的name的唯一。
removeTab
删除时遍历找到对应的tab,然后把当前激活的activeIndex
设置到当前tab的下一个或上一个
methods:
removeTab(target) {
// 删除的是当前选中的页面
if (this.activeIndex === target) {
this.openTab.forEach((item, index) => {
if (item.name == target) {
let nextTab = item[index + 1] || item[index - 1];
if (nextTab) {
this.activeIndex = nextTab.name;
}
}
});
}
var i = 0;
this.openTab.forEach((item, index) => {
if (item.name == target) {
return (i = index);
}
});
this.openTab.splice(i, 1);
// 更新路由
this.$router.push({ path: this.openTab[this.openTab.length - 1].name });
},
clickTab(tab) {
this.activeIndex = tab.paneName;
this.$router.push({ path: this.activeIndex });
},
watch: {
$route(to, form) {
//当路由更新进行tab切换
var flag = false;
// 当前页面菜单已打开,直接切换过去
if (this.openTab) {
for (let i = 0; i < this.openTab.length; i++) {
if (
to.path == this.openTab[i].name || to.path.includes(this.openTab[i].name)
) {
//openTab中已存在?
this.activeIndex = this.openTab[i].name;
flag = true;
break;
}
}
}
// 打开新的页面tab
if (!flag) {
let obj = {
title: to.meta.title,
name: to.path,
closable: true,
componentName: to.matched[1].components.default.name //路由只缓存到第1层,更深层的视图不考虑
};
this.activeIndex = to.path;
this.openTab.push(obj);
}
},
}
通过watch
监测路由的变动对tab进行处理,也是遍历找到对应的tab进行切换,当路由切换时不仅route-view会进行改变,tab也会跟着更新。
注意当点击导航打开的一个新的路由时需要添加新的tab,同时需要从当前路由配置中拿出对应页面的组件名name存储到componentName中,这里拿取第一层是因为目前不考虑多级路由情况的。
以上就是本编文章的所有内容了,重点有建立tab和视图,实现删除功能,到最后的watch方式监听路边来切换tab,详细说明了实现过程,如果你觉得好的话可以关注我,共同努力,共同进步。我目前是坚持每月都会发布前端相关文章。感谢~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。