vue+elementUI实现tab路由切换

vue+elementUI实现tab路由切换


这个tab其实实现很久了,已经在我好几个项目中使用了,很早之前就想记录下来的,一直拖拖拖到现在emmmm…
最开始写这个tab的时候去看了很多篇实现tab的文章,先后也试了很多他们写的,因为项目框架的不同,总是有大大小小的问题,推翻重做了多次,依旧没能实现。最后还是自己一点一点理解后堆出来了。(原本觉得很难,理解后发现并没有那么难,所以不管做什么,理解真的很重要!!!)
实现效果:
vue+elementUI实现tab路由切换_第1张图片

直接上代码!
1.实现tab组件

TabComponent.vue

<template>
  <div class="app-wrap">
    <!-- 此处放置el-tabs代码 -->
    <div class="template-tabs">
      <el-tabs
        v-model="editableTabsValue"
        type="card"
        closable
        @tab-click="tabClick"
        @tab-remove="removeTab">
        <el-tab-pane
          v-for="(item, index) in editableTabs"
          :key="item.name"
          :label="item.title"
          :name="item.name"
        >
        </el-tab-pane>
      </el-tabs>
    </div>
  </div>
</template>

<script>

  export default {
    name: "TabComponent",
    data(){
      return{
      }
    },
    methods: {
     //点击切换tab
      tabClick(tab){
        let path = tab.name;
        this.$store.commit('setTabName', path);
        this.$router.push({path: path});
      },
      //点击移除tab
      removeTab(targetName){
        if(targetName === "/home"){
          return;
        }
        let tabs;
        tabs = typeof this.editableTabs ==='string'? JSON.parse(this.editableTabs):this.editableTabs;

        let activeName = this.editableTabsValue;
        if (activeName === targetName) {
          // 设置当前激活的路由
          tabs.forEach((tab,index) =>{
            if(tab.name === targetName){
              let nextTab = tabs[index +1];
              let preTab = tabs[index -1];

              if(nextTab){
                activeName = nextTab.name;
              }else if(preTab){
                activeName = preTab.name;
              }else {
                activeName = "/home";
              }
            }
          });
        }

        let tab1;
        tab1 = tabs.filter(tab => tab.name !== targetName);

        this.$store.commit('addTab', tab1);
        this.$store.commit('setTabName', activeName);

        this.$router.push({path: activeName});
      }
    },
    computed: {
    //存放所有tab的数组 
      editableTabs() {
        let tabs;
        let data = this.$store.getters.editableTabs;
        tabs = typeof data === 'string'? JSON.parse(data):data;
        return tabs;
      },
      //当前tab 初始默认为首页(/home)
      editableTabsValue() {
        return this.$store.getters.editableTabsValue;
      }
    },
    watch: {
      //监听路由的变化来实现添加或切换tab
      '$route':function (to) {
        let flag = false;
        let tabs = this.editableTabs;
        let route = this.editableTabsValue;
        for (let i = 0;i < tabs.length;i++) {
          if (tabs[i].name === to.path) {
            flag = true;
            //设置当前tab为当前路由
            this.$store.commit('setTabName', to.path);
            break;
          }
        }
        if (!flag) {
          let data = {
            title: to.meta.label,
            name: to.path,
          };
          tabs.push(data);
          route = to.path;
          //设置tab数组
          this.$store.commit('addTab', tabs);
          this.$store.commit('setTabName', route);
        }
      }
    },
  }
</script>

<style scoped>
  .template-tabs {
    background-color: white;
  }
</style>

store文件夹下 index.js



import {Msg} from '../../tools/message/Msg';
import {Auth} from './auth';
export default {
  state: {
    /** 当前tab   '/home' 可以更改为自己默认的页面*/
    editableTabsValue:Auth.getEditableTabsValue() || '/home',
    /*tab数组*/
    editableTabs:Auth.getEditableTabs() || [{title:'首页',name:'/home'}],
  },
  /** 计算属性 */
  getters: {},
  /** 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation */
  mutations: {
  //退出登录时注销tab
    ACCOUNT_LOGOUT_FAILURE(state) {
      state.editableTabsValue = '/home';
      state.editableTabs = [{title:'首页',name:'/home'}];
 //其他代码
      Auth.removeEditableTabs();
      Auth.removeEditableTabsValue()
    },
   //设置当前tab数组
    addTab(state,data){
      state.editableTabs = data;
      Auth.setEditableTabs(data);
    },
    //设置当前tab
    setTabName(state,data){
        state.editableTabsValue = data;
        Auth.setEditableTabsValue(data);
    }
  },
  /** Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。 */
  actions: {
    /** 登出 */
    accountLogoutSubmit({commit}, params) {
      return new Promise((resolve, reject) => {
        UserCountService.logout(params).then((res) => {
          commit('ACCOUNT_LOGOUT_FAILURE');
          resolve()
        }).catch(err => {
          commit('ACCOUNT_LOGOUT_FAILURE');
          resolve()
        })
      })
    },
  }
}

store文件夹下 auth.js

import Cookies from 'js-cookie'

const sessionStorage = window.sessionStorage;
export class Auth {
  static getEditableTabs() {
    return sessionStorage.getItem('user.editableTabs')
  }


  static setEditableTabs(value = []) {
    return sessionStorage.setItem('user.editableTabs', JSON.stringify(value))
  }

  static removeEditableTabs() {
    return sessionStorage.removeItem('user.editableTabs')
  }

  static getEditableTabsValue() {
    return sessionStorage.getItem('user.editableTabsValue')
  }

  static setEditableTabsValue(value) {
    return sessionStorage.setItem('user.editableTabsValue', value)
  }

  static removeEditableTabsValue() {
    return sessionStorage.removeItem('user.editableTabsValue')
  }
}

store文件夹下getter.js

export const getters = {
  editableTabsValue:state => state.user.editableTabsValue,
  editableTabs:state => state.user.editableTabs,
};

需要使用tab组件的地方

<el-main style="background-color: #F0F0F7">
        <div>

          <tab-component></tab-component>
          <keep-alive>
            <div style="background-color: white" >
              <router-view/>
            </div>

          </keep-alive>
        </div>
      </el-main>

你可能感兴趣的:(vue,前端,elementUI,vue.js,前端,tab)