vue使用el-tabs实现标签页(内存+vuex)

vue使用el-tabs实现标签页(内存+vuex)
效果图:
1:
在这里插入图片描述

2:
在这里插入图片描述
3:内存中
在这里插入图片描述

这是一个组件,例如: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>

<style scoped lang="scss">
// 组件高度
$tabLineHeight:30px;
// 边框颜色
$borderColor: #488ba0;
// 未激活的以及tab本身的背景
$background: #09142e;
// 激活的标签的背景
$background-active: #488ba0;
// 未激活标签的字体颜色
$fontColor:#30c0cd;
.page-tabs-index{
  height: $tabLineHeight;
  ::v-deep .el-tabs{
  }
  // 底部横线
  ::v-deep .el-tabs__header{
    height: $tabLineHeight;
    background: $background;
    box-sizing: border-box;
    border-bottom: 1px solid $borderColor;
  }
  // 左右滚动按钮
  ::v-deep .el-tabs__nav-prev {
    height: $tabLineHeight;
    line-height: $tabLineHeight;
  }
  ::v-deep .el-tabs__nav-next {
    height: $tabLineHeight;
    line-height: $tabLineHeight;
  }
  ::v-deep .el-tabs__nav{
    border-radius: 0;
    border-left: none;
    border-right: none;
    border-top: none ;
  }

  ::v-deep .el-tabs__item{
    height: $tabLineHeight;
    line-height: $tabLineHeight;
    border-color: $borderColor;
    color: #fff;
    border-right: 1px solid $borderColor;
    //border-radius: 3px 3px 0 0;
  }

  // 左侧第一个
  ::v-deep .el-tabs__item.is-active:first-child{
    border-left: none;
  }

  ::v-deep .el-tabs__item:not(.is-disabled){
    color: $fontColor;
    border-left: none;
    border-top: 2px solid transparent;
  }

  ::v-deep .el-tabs__item.is-active{
    border-bottom: 1px solid $background-active;
    border-top: 2px solid $borderColor;
    border-right: 1px solid $borderColor;
    background: $background-active;
    color: #fff;
  }
}
</style>
然后还需要创建一个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>
 
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_小郑有点困了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值