标签页放在main中
标签页el-tabs主要属性:
(1)editableTabsValue:高亮表示被选中的标签页(通过name标识)
(2)editableTabs:标签页数组(存储所有的标签页信息),属性:name、title
<!-- 标签页-->
<el-tabs v-model="editableTabsValue" type="card" closable @tab-remove="removeTab" @tab-click="selectTab">
<el-tab-pane
v-for="(item, index) in editableTabs"
:key="item.name"
:label="item.title"
:name="item.name"
>
</el-tab-pane>
</el-tabs>
editableTabsValue、editableTabs存放在store中
1、点击菜单项生成新的标签页
点击菜单项生成新的标签页,添加新的标签页前要判断标签页数组中是否已经包含该标签页,如果已经拥有该标签页,只需要选中该标签页。
示例:
通过点击事件addTabs将菜单项的title和name添加到标签页数组中
<el-menu-item index="/index" @click="addTabs({title:'首页',name:'/index'})">
<i class="el-icon-s-home"></i>
<span slot="title">首页</span>
</el-menu-item>
<el-menu-item :index="item.name" :route="{path:item.path}" v-for="item in menu.children" @click="addTabs(item)">
<template slot="title">
<i :class="item.icon"></i>
<span>{
{
item.title}}</span>
</template>
</el-menu-item>
store中对应的addTabs方法,添加一个新标签项同时将其置为高亮,即选中状态。
//添加标签页
addTab(state,item){
//当标签页数组中没有当前标签时才添加。
let index = state.editableTabs.findIndex(e => e.name===item.name)
if(index===-1){
state.editableTabs.push({
title: item.title,
name: item.name
})
}
//将新添加标签页激活:高亮
state.editableTabsValue = item.name
}
因为标签页数组editableTabs是动态更新的,所以在main中要动态获取editableTabsValue 、editableTabs值。通过computed实现。
如下:
//动态监测变量值
computed:{
editableTabsValue: {
get(){
return this.$store.state.menus.editableTabsValue;
},
set(val){
this.$store.state.menus.editableTabsValue = val;
}
},
editableTabs:{
get(){
return this.$store.state.menus.editableTabs;
},
set(val){
this.$store.state.menus.editableTabs = val;
}
}
},
2、点击标签页项实现页面跳转
在标签页中添加绑定事件@tab-click=“selectTab”
标签页部分
<el-tabs v-model="editableTabsValue" type="card" closable @tab-remove="removeTab" @tab-click="selectTab">
<el-tab-pane
v-for="(item, index) in editableTabs"
:key="item.name"
:label="item.title"
:name="item.name"
>
通过路由跳转函数selectTab实现页面跳转。
前提,菜单项的name要和路由项的name相同
//点击某个标签页实现路由跳转
selectTab(target){
//新知识点
//this.$router.push()不仅可以通过path跳转,还可以通过name跳转
this.$router.push({
name:target.name}).catch(err => {
console.log(err)
})
}
3、bug
bug1: 当刷新页面时,之前显示的标签页都消失了。
原因:vuex store中的数据会随着页面刷新恢复默认。
解决方法:将editableTabs、editableTabsValue存放在session中。
在页面刷新时将vuex里面的信息保存在sessionStorage,页面加载时读取session中的信息,并加载到store中。
在App.vue中操作
// 解决刷新页面后,页面path和页面内容不同bug
created() {
//在页面刷新时将vuex里面的信息保存在sessionStorage
window.addEventListener("beforeunload",() => {
sessionStorage.setItem("editableTabs",JSON.stringify(this.$store.state.menus.editableTabs))
sessionStorage.setItem("editableTabsValue",this.$store.state.menus.editableTabsValue)
})
//页面加载时读取session中的信息,并加载到store中
sessionStorage.getItem("editableTabsValue")&&this.$store.commit("getEditableTabsValue",sessionStorage.getItem("editableTabsValue"))
sessionStorage.getItem("editableTabs")&&this.$store.commit("getEditableTabs",JSON.parse(sessionStorage.getItem("editableTabs")))
},
对应store中的相关函数,getEditableTabsValue、getEditableTabs
//从session中获取editableTabsValue
getEditableTabsValue(state,editableTabsValue){
state.editableTabsValue = editableTabsValue
},
//从session中获取editableTabs
getEditableTabs(state,editableTabs){
state.editableTabs = editableTabs
},
bug2: 如果直接通过url访问某个菜单项,此时store和session中都没有相关标签页信息,那么此时标签页会显示空白。所以在App.vue中增加一个监听watch
//监控
//当用户通过输入url访问界面时,此时store中和session中可能都没有该页面标签页的信息,这时就要通过watch解决
//原理:在我们访问对应path之前,就把path对应的title、name加入到store中
watch: {
$route(to,from){
//当我前往的路由路径不是login时,就把该路由信息加入到标签页数组中
if(to.path !== '/login'){
let obj = {
title: to.meta.title,
name: to.name
}
this.$store.commit("addTab",obj)
}
}
}
注意:此处使用的时route。
route和router区别
bug3: 用户退出后,store的信息没有恢复默认
logout(){
this.$axios.post('/logout').then(res => {
//清除本地用户信息
localStorage.clear()
sessionStorage.clear()
//清除store中token信息
this.$store.commit("resetState");
//清除store中的标签页信息
this.$store.commit("resetEditableTabs")
this.$store.commit("resetEditableTabsValue")
router.push('/login')
})
},