创建文件

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// 应用初始状态
const state = () => ({
  tabMenu: [],
  activeIndex: '/',
  includePage: [],
})

// getters
const getters = {

}

// actions
const actions = {

}

// mutations
const mutations = {
  // 更新tabs
  updateTabs (state, data) {
    if (state.activeIndex === data.path) return
    state.activeIndex = data.path
    const isTab = state.tabMenu.some(item => item.path === data.path)
    if (!isTab) {
      state.tabMenu.push(data)
      const activePage = data?.meta?.activePage || ''
      state.includePage.push(activePage)
    }
  },

  // 删除tabs
  deleteTabs (state, path) {
    const index = state.tabMenu.findIndex(item => item.path === path);
    state.tabMenu.splice(index, 1)
    state.includePage.splice(index, 1)
    const href = state.tabMenu.at(-1).path
    router.push(href)
  },

  //初始化添加tabs
  initTabs (state) {
    state.tabMenu = []
    state.activeIndex = '/'
    state.includePage = []
  },

  //刷新页面
  getRefreshTabs (state) {
    const tab = { path: '/work', name: '工作台', meta: { activePage: 'Work' } }
    state.tabMenu.push(tab)
    state.includePage.push(tab.meta.activePage)
    state.activeIndex = tab.path
    router.push(tab.path)
  },
}

// 创建 store 实例
export default new Vuex.Store({
    state,
    mutations
})

首页代码

<el-tabs :value="activeIndex"
         type="card"
         closable
         @tab-click="tabClick"
         @tab-remove="tabRemove">
  <el-tab-pane v-for="item in tabMenu"
               :key="item.path"
               :label="item.name"
               :name="item.path">
  </el-tab-pane>
</el-tabs>

 <!-- 这里是会被缓存的视图组件 -->
<keep-alive :include="includePage">
  <router-view></router-view>
</keep-alive>

动态渲染逻辑

methods: {
  ...mapMutations('tabs', ['updateTabs', 'deleteTabs', 'initTabs', 'getRefreshTabs']),
    //选中的菜单项
    handleSelect (path, keyPath) {
      console.log(path, keyPath)
      this.$router.push(path)
    },

    // tab切换时,动态的切换路由
    tabClick (tab) {
      this.$router.push(tab.name)
    },

    tabRemove (tab) {
      // 首页不可删除
      if (tab === '/work') return
      this.deleteTabs(tab)
    },

},

 // 计算路由缓存
computed: {
    ...mapState('tabs', ['tabMenu', 'includePage', 'activeIndex']),
    
},

  // 监听路由
watch: {
    '$route' (to) {
      this.updateTabs(to)
    }
}

//初始化路由
created () {
  this.initTabs()
},

mounted () {
  this.getRefreshTabs()
},
  

路由配置

const router = new VueRouter({
    routes = [
    	{
        path: '/',
        component: Home,
        name: '导航一',
        iconCls: 'el-icon-message',//图标样式class
        children: [
            { path: '/main', component: Main, name: '主页', meta: { activePage: 'Main'}},
            { path: '/table', component: Table, name: 'Table', meta: { activePage: 'Table'} },
            { path: '/form', component: Form, name: 'Form', meta: { activePage: 'Form'}  },
            { path: '/user', component: User, name: '列表', meta: { activePage: 'User'}  },
        	]
    	}
	]
})
Last Updated:
Contributors: pengrengui