Vue2+ElementUI实现NavMenu与Tabs联动

使用vue-router、NavMenu(导航菜单)与Tabs(标签页)联动

app.Vue

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>

export default {
    name: 'app'
}
</script>

新建布局页与tab页并注册路由

router/index.js : 

import Vue from 'vue'
import VueRouter from 'vue-router'
import layout from '@/views/layout/index.vue'
import test1 from '@/views/test1/test1.vue'
import test2 from '@/views/test2/test2.vue'

const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (location) {
  return originalPush.call(this, location).catch(err => err)
}

Vue.use(VueRouter)


const routes = [
  {
    path:'/',
    component:layout,
    children:[
      {
        path:'/test1/test1',
        name:'test1',
        component: test1
      },
      {
        path:'/test2/test2',
        name:'test2',
        component: test2
      }
    ]
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

views/layout/index.vue :

使用elementUI布局容器,el-container、el-main,并使用el-menu导航菜单和el-tabs标签页;

引入vuex的mapActions,在菜单点击、标签页点击时处理标签列表与当前标签索引

<template>
  <div>
    <el-container>
      <el-aside width="200px">
        <!-- :default-active="$route.path"  对应menuItem的index -->
        <el-menu mode="vertical" :default-active="$route.path" class="el-menu-vertical-demo">
          <el-menu-item 
          v-for="(item,index) in navList"
          :index="item.route"
          @click="handClick(item)">{{item.title}}</el-menu-item>
          
        </el-menu>
      </el-aside>
      <el-main>
        <el-tabs v-model="activeName" @tab-click="tabClick">
          <el-tab-pane :label="item.title" :name="item.name" v-for="(item, index) in tabsPage"
            :key="item.name"></el-tab-pane>

        </el-tabs>
        <router-view></router-view>
      </el-main>
    </el-container>

  </div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
  components: {
     
  },
  data() {
    return {
      navList: [
        { route: '/test1/test1', name: 'test1', title: '测试页面1' },
        { route: '/test2/test2', name: 'test2', title: '测试页面2' }
      ]
    }
  },
  mounted() {

  },
  computed: {
    activeName: {
      get() {
        console.log(this.$store.state.curentTab)
        return this.$store.state.curentTab
      },
      set(){}
    },
    tabsPage: {
      get() {
        return this.$store.state.tabsPage
      }
    }
  },
  methods: {
    ...mapActions({
      handClick: 'editableTabs',
      setActiceTab: 'setActiceTab'
    }),
    
    tabClick(tab, event) {

      let cur = this.tabsPage[tab.index]
      this.$router.push({ name: cur.name })
    }
  },
}
</script>
<style scoped></style>

vuex:store.js处理标签数据和路由跳转

tabs使用的标签数组在vuex中处理,如果数组中没有,添加一个元素并跳转,如果已存在,直接跳转;同时将修改当前标签页索引curentTab,tabs使用

 v-model="activeName" 来绑定值,即选中选项卡的 name
import router from '@/router'
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1,
    tabsPage: [],
    curentTab: ''
  },
  getters: {
  },
  mutations: {
    setActiceTab(state, value) {
      
      state.curentTab = value
    },
    editableTabs: (state, obj) => {
      
      let arr = Array.from(state.tabsPage)

      //判断目前tab列表是否已包含该页面
      let hasPage = arr.some(item => item.name == obj.name)
      if (hasPage) { //如果存在直接跳转
        router.push({ name: obj.name })
      }
      else { //如果没有,添加并跳转
        state.tabsPage.push({
          name: obj.name,
          route: obj.route,
          title:obj.title
        })
        router.push({ name: obj.name })
      }
      state.curentTab = obj.name
    }
  },
  actions: {
    editableTabs(context, obj) {
      context.commit('editableTabs', obj);
    },
    setActiceTab(context,obj){
      context.commit('setActiceTab',obj)
    }
  },
  modules: {
  }
})

效果:

posted @ 2025-06-22 19:14  陈鹏昱Chen  阅读(67)  评论(0)    收藏  举报