Vue + elementui implementation of multiple tabs coexistence

Time:2019-12-12

This theme, which was created a year ago, has also written some content, because the experience in the application is not perfect, and there are only drafts.

After many platform practices and iterations, some functions have been added and decreased, and finally the most simplified version has been returned. It has been applied to most scenarios, and can be expanded if necessary.

Key logic

  • Use keep alive to cache tabs
  • Update label information through the beforeeach method of Vue router
  • Save label information through vuex
  • Make the closed page not cached through vuex

Core code

Define the cross page variable of vuex (store / index. JS)

import Vuex from 'vuex'
 Vue.use(Vuex)
 export default new Vuex.Store({
  state: {
   worktab: {
    list: [
     {
      name: 'my',
      Tabname: 'home page',
      path: '/page/my'
     }
    ],
    current: {
     name: 'my',
     Tabname: 'home page',
     path: '/page/my'
    }
   },
   closingPage: ''
  },
  mutations: {
   worktabRemove (state, p) {
    //Close tag
    let ind = state.worktab.list.findIndex(s => s.name === p)
    if (ind > -1) {
     //Clean up keep alive - start
     state.closingPage = state.worktab.list[ind].name
     //Clean up keep alive - end
     state.worktab.list.splice(ind, 1)
    }
    if (p === state.worktab.current.name) {
     //Is the current page, return to the previous page
     router.back()
    }
   },
   worktabRoute (state, p) {
    let ind = state.worktab.list.findIndex(s => s.name === p.to.name)
    if (ind > -1) {
     //Label already exists
     state.worktab.current = state.worktab.list[ind]
    } else {
     //Label does not exist, create a new one now
     state.worktab.list.push(p.to)
     state.worktab.current = p.to
    }
    state.closingPage = ''
   }
  },
  actions: {
   worktabRemove ({commit}, p) {
    commit('worktabRemove', p)
   },
   worktabRoute ({commit}, p) {
    commit('worktabRoute', p)
   }
  },
  strict: debug
 })

Define the worktab tab tab tab component, which is referenced in the main container

<template>
  <div>
   <el-tabs v-model="activeTab" type="card" @tab-remove="removeTab" @tab-click="clickTab">
    <el-tab-pane
     v-for="t in worktabs"
     :key="t.name"
     :label="t.tabname"
     :name="t.name"
     :closable="t.name !== 'my'"
    >
    </el-tab-pane>
   </el-tabs>
  </div>
 </template>
 <script>
 export default {
  created () {
   //When you come in but not the home page, wait for the list to load and then update the current
   setTimeout(() => {
    this.activeTab = this.$store.state.worktab.current.name
   }, 500)
  },
  watch: {
   '$store.state.worktab.current' (tab) {
    this.activeTab = tab.name
   }
  },
  computed: {
   worktabs () {
    return this.$store.state.worktab.list
   }
  },
  data () {
   return {
    activeTab: 'name'
   }
  },
  methods: {
   clickTab (tab) {
    this.$router.push(this.worktabs[1 * tab.index].path)
   },
   removeTab (name) {
    this.$store.dispatch('worktabRemove', name)
   }
  }
 }
 </script>

Routing control updates label information through beforeeach

import Vue from 'vue'
 import VueRouter from 'vue-router'
 import store from '@/store'
 import Page from '../components/console/Page.vue'
 import My from '../components/console/My.vue'
 Vue.use(VueRouter)
 //Associate routes with components
 const routes = [
  {
   name: 'root',
   path: '/'
  },
  {
   path: '/page',
   component: Page,
   children: [
    {
     name: 'my',
     path: 'my',
     component: My,
     meta: {
      Tabname: 'personal home page'
     }
    }
   ]
  }
 ]
 //Create router
 const router = new VueRouter({
  routes
 })
 router.beforeEach((to, from, next) => {
  next()
  store.dispatch('worktabRoute', {
   to: {
    name: to.name ? to.name : '',
    tabname: (to.meta && to.meta.tabname) ? to.meta.tabname : '',
    path: to.path
   },
   from: {
    name: from.name ? from.name : '',
    tabname: (from.meta && from.meta.tabname) ? from.meta.tabname : '',
    path: from.path
   }
  })
  return
 })
 export default router

The main container uses the closengpage variable to clean up the cache of closed pages in time


<template>
  <div>
   <cp-worktab></cp-worktab>
   <div>
    <keep-alive :exclude="closingPage">
     <router-view></router-view>
    </keep-alive>
   </div>
  </div>
 </template>
 <script>
 import Worktab from '../module/Worktab'
 export default {
  components: {
   cpWorktab: Worktab
  },
  data () {
   return {}
  },
  computed: {
   closingPage () {
    return this.$store.state.closingPage
   }
  }
 }
 </script>

summary

The above is the method of Vue + elementui to realize the coexistence of multiple tabs introduced by Xiaobian. I hope it can help you. If you have any questions, please leave me a message, and Xiaobian will reply you in time!