目录
一、el-tabs常用写法
<el-tabs v-model="tabName" type="card" :closable="closable" @tab-click="clickTab" @edit="handleTabsEdit">
<el-tab-pane label="详情" name="first">
<div><div/>
</el-tab-pane>
<el-tab-pane label="其他" name="second">
<div><div/>
</el-tab-pane>
</el-tabs>
data() {
return {
tabName: "first",
}
}
二、vue使用el-tabs实现标签页(内存+vuex)
这是一个组件,例如:pageTabs.vue(组件是可以做到独立监听路由变化的,所以不需要外部调用什么内部的方法,所以可以抽离成为一个组件),监听路由改变进行新增标签,以及el-tabs组件的切换,删除
代码:
<template>
<div class="page-tabs-index">
<el-tabs v-model="activeRoute" type="card" :closable="closable" @tab-click="clickTab" @edit="handleTabsEdit">
<el-tab-pane
:key="index"
v-for="(item, index) in tabs"
:label="item.title"
:name="item.route"
>
<span slot="label" @click.middle="removeTabByMiddle(item.route)">{
{item.title}}</span>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
export default {
data(){
return{
closable: false,
activeRoute:'',
tabs:[]
}
},
methods:{
// 增删tabs
handleTabsEdit(targetName,action){
// console.log('tab增删:',targetName,action);
if(action === 'remove'){
this.methods('removeTab',targetName);
this.methods('checkClosable');
}
},
// 鼠标中键删除
removeTabByMiddle(route){
if(this.closable){
this.methods('removeTab',route);
this.methods('checkClosable');
}
},
// 点击tab,item是被选中的标签的vue实例
clickTab(item){
if(this.$route.name === item.name){
return ;
}
// console.log('tab切换:', item.name);
this.$router.push({name:item.name})
},
// 这里需要配合keep-alive的includeAPI,设置vuex的缓存list,以实现tab关闭后vue不缓存该页面
// 加载tabs缓存
loadTabs() {
const pageTabs = sessionStorage.getItem('page-tabs');
if (pageTabs) {
this.tabs = JSON.parse(pageTabs);
}
this.$store.commit('setKeepAliveList',this.tabs.map(i=>i.route));
},
// tab切换更新
updateTabs() {
const route = this.$route.name;
const title = route;
if(!route || route === 'index'){
// 这里是处理layout中第一次加载会是null,后续由监听$route更新,(index路由是引导用的,不需要)
// 而如果是当从没有tabs的页面跳转过来时,不走下面,将不会变更当前激活
return;
}
// 新增
if (!this.tabs.find(i => i.route === route)) {
this.tabs.push({ route, title });
}
this.activeRoute = route;
// this.$route.meta.keepAlive = true;
// 缓存tabs
sessionStorage.setItem('page-tabs', JSON.stringify(this.tabs));
this.$store.commit('setKeepAliveList',this.tabs.map(i=>i.route));
},
// 移除tab
removeTab(route) {
// 保存index
let index = this.tabs.findIndex(i => i.route === route);
this.tabs = this.tabs.filter(i => i.route !== route);
this.$store.commit('setKeepAliveList',this.tabs.map(i=>i.route));
// 如果删除的是当前的route
if (this.activeRoute === route) {
// 将当前激活route切换为刚才删除的后一个
if (index > this.tabs.length-1 ) {
index -= 1 ;
}
this.activeRoute = this.tabs[index].route;
// this.$route.meta.keepAlive = false;
this.$router.push({ name: this.activeRoute });
}
// 缓存tabs
sessionStorage.setItem('page-tabs', JSON.stringify(this.tabs));
},
// 检查是否可以继续删除
checkClosable() {
this.closable = this.tabs.length > 1;
}
},
created(){
// this.lists = this.$store.state.other.houseList;
},
mounted(){
this.loadTabs()
this.updateTabs()
this.checkClosable()
},
watch:{
$route(){
this.loadTabs()
this.updateTabs()
this.checkClosable()
}
}
}
</script>
然后还需要创建一个vuex
export default {
name: 'pageTabs',
state: {
keepAliveList:[],
},
mutations: {
setKeepAliveList (state, list) {
state.keepAliveList = list
}
}
}
然后就去入口页面引入使用即可,例如App.vue
<template>
<div id="app" class="biggbox">
<pageTabs></pageTabs>
<!-- 中部 -->
<transition>
<router-view></router-view>
</transition>
</div>
</template>
还可以用keepAlive
<keep-alive :include="keepAliveList">
<router-view ></router-view>
</keep-alive>
三、vue使用el-tabs实现标签页,切换标签页传值
// pageTabs
<template>
<div class="page-tabs-index">
<el-tabs v-model="activeRoute" type="card" :closable="closable" @tab-click="clickTab" @edit="handleTabsEdit">
<el-tab-pane
v-for="item in tabs"
:key="item.route"
:label="item.str"
:name="item.route"
>
<span slot="label">{
{ item.str }}</span>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
export default {
name: 'PageTabs',
data() {
return {
closable: false,
activeRoute: '',
tabs: []
}
},
watch: {
$route() {
this.loadTabs()
this.updateTabs()
this.checkClosable()
}
},
created() {},
mounted() {
this.loadTabs()
this.updateTabs()
this.checkClosable()
},
methods: {
// 增删tabs
handleTabsEdit(targetName, action) {
if (action === 'remove') {
this.removeTab(targetName)
this.checkClosable()
}
},
// 点击tab,item是被选中的标签的vue实例
clickTab(item) {
if (this.$route.route === this.tabs[item.index].route) {
return
}
// 页面传值
this.$router.push({ name: this.tabs[item.index].route, query: this.tabs[item.index].id })
},
// 这里需要配合keep-alive的includeAPI,设置vuex的缓存list,以实现tab关闭后vue不缓存该页面
// 加载tabs缓存
loadTabs() {
const pageTabs = sessionStorage.getItem('page-tabs')
if (pageTabs) {
this.tabs = JSON.parse(pageTabs)
}
this.$store.dispatch('tabs/setKeepAliveList', this.tabs.map(i => i.route))
},
// tab切换更新
updateTabs() {
const route = this.$route.name
const num = this.$store.state.tabs.tabList.length - 1
const str = this.$store.state.tabs.tabList[num].title
const id = this.$store.state.tabs.tabList[num].index === '' ? '' : JSON.parse(this.$store.state.tabs.tabList[num].index)
if (!route || route === 'index') {
// 这里是处理layout中第一次加载会是null,后续由监听$route更新,(index路由是引导用的,不需要)
// 而如果是当从没有tabs的页面跳转过来时,不走下面,将不会变更当前激活
return
}
// 新增
if (!this.tabs.find(i => i.route === route)) {
this.tabs.push({ route, str, id })
} else {
// 路由相同替换参数
this.tabs.forEach(item => {
if (item.route === route) {
item.id = id
}
})
}
this.activeRoute = route
// this.$route.meta.keepAlive = true;
// 缓存tabs
sessionStorage.setItem('page-tabs', JSON.stringify(this.tabs))
this.$store.dispatch('tabs/setKeepAliveList', this.tabs.map(i => i.route))
},
// 移除tab
removeTab(route) {
// 保存index
let index = this.tabs.findIndex(i => i.route === route)
this.tabs = this.tabs.filter(i => i.route !== route)
this.$store.dispatch('tabs/setKeepAliveList', this.tabs.map(i => i.route))
// 如果删除的是当前的route
if (this.activeRoute === route) {
// 将当前激活route切换为刚才删除的后一个
if (index > this.tabs.length - 1) {
index -= 1
}
this.activeRoute = this.tabs[index].route
// this.$route.meta.keepAlive = false;
// 跳转页面保留参数
this.$router.push({ name: this.activeRoute, query: this.tabs[index].id })
}
// 缓存tabs
sessionStorage.setItem('page-tabs', JSON.stringify(this.tabs))
},
// 检查是否可以继续删除
checkClosable() {
this.closable = this.tabs.length > 1
}
}
}
// router/index
// 路由守卫
router.afterEach((to, from) => {
const ind = to.query === undefined ? '' : to.query
// 处理一下要的参数,新增tab的时候用到
$store.dispatch('tabs/steTabList', { title: to.meta.title, path: to.path, query: to.query, index: JSON.stringify(ind) })
})
有用请点赞,养成良好习惯!
疑问、交流、鼓励请留言!