vue2 实现后台管理系统左侧菜单联动实现 tab根据路由切换联动内容

简介: vue2 实现后台管理系统左侧菜单联动实现 tab根据路由切换联动内容

效果图:

话不多说上代码

一、vue页面

home页代码

<template>
  <div>
    <el-container>
      <el-aside width="collapse ? 200px : 35px">
        <el-menu
          :collapse="collapse"
          :default-active="this.$store.state.title"
          class="el-menu-vertical-demo"
          unique-opened
          active-text-color="#ffd04b"
          text-color="#fff"
          background-color="transparent"
          @select="hh"
        >
          <el-button @click="collapseToggle" style="margin-top: 10px; margin-bottom: 10px">
            <i class="el-icon-s-unfold" v-if="collapse" />
            <i class="el-icon-s-fold" v-else />
          </el-button>
          <leftMenu :dataToSon="this.$store.state.tree" />
        </el-menu>
      </el-aside>
      <el-container>
        <el-header class="header">Header</el-header>
        <el-main>
          <multipleTabs></multipleTabs>
        </el-main>
        <el-footer>Footer</el-footer>
      </el-container>
    </el-container>
  </div>
</template>
<script>
import leftMenu from '@/views/home/leftMenu'
import multipleTabs from '@/views/home/multipleTabs'
export default {
  // eslint-disable-next-line vue/multi-word-component-names
  name: 'home',
  components: {
    leftMenu,
    multipleTabs
  },
  data () {
    return {
      collapse: false
    }
  },
  mounted () {
  },
  methods: {
    hh (e) {
      this.$store.commit('tab', e)
    },
    collapseToggle () {
      this.collapse = !this.collapse
    }
  }
}
</script>
<style scoped>
.el-header, .el-footer {
  background: url("../../../src/assets/111.jpg");
  color: #333;
  text-align: center;
}
.el-aside {
  text-align: center;
}
.el-main {
  color: #333;
  text-align: center;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
  min-width: 200px;
  height: 100vh;
}
>>> .el-menu--collapse .menu {
  display: none;
}
>>> .el-menu--collapse .el-submenu__icon-arrow {
  display: none;
}
span {
  display: none;
}
.el-menu-vertical-demo {
  background: url("../../../src/assets/111.jpg");
  height: 100vh;
  border-right: 0;
}
</style>

leftMenu.vue代码

<template>
  <div>
    <fragment v-for="(item, index) in list" :key="index">
      <!-- 非叶子节点 -->
      <el-submenu v-if="item.children" :index="item.path">
        <template slot="title">
          <i class="el-icon-location"></i>
          <span class="menu" slot="title">{{ item.name }}</span>
        </template>
        <left-menu :dataToSon="item.children"></left-menu>
      </el-submenu>
      <!-- 叶子节点(功能节点) -->
      <el-menu-item v-else :index="item.path">
        <i class="el-icon-menu"></i>
        <span class="menu" slot="title">{{ item.name }}</span>
      </el-menu-item>
    </fragment>
  </div>
</template>
<script>
import leftMenu from '../../../src/views/home/leftMenu.vue'
export default {
  // eslint-disable-next-line vue/multi-word-component-names
  name: 'leftMenu',
  components: {
    leftMenu
  },
  props: ['dataToSon'],
  data () {
    return {
      isCollapse: false,
      list: []
    }
  },
  mounted () {
    this.list = this.dataToSon
  },
  methods: {
    handleOpen (key, keyPath) {
      console.log(key, keyPath)
    },
    handleClose (key, keyPath) {
      console.log(key, keyPath)
    }
  }
}
</script>
<style scoped>
</style>

multipleTabs.vue代码

<template>
  <div>
    <el-tabs v-model="activeTab" type="card" closable @tab-remove="rem">
      <el-tab-pane
        v-for="item in this.$store.state.tabOne"
        :key="item.id"
        :label="item.name"
        :name="item.path"
      >
        <router-view :name="item.path" v-slot="{Component}">
          <keep-alive>
            <component :is="Component"></component>
          </keep-alive>
        </router-view>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
  name: 'MultipleTabs',
  computed: {
    ...mapState({
      vuexActiveTab: 'title'
    }),
    activeTab: {
      get () {
        return this.vuexActiveTab
      },
      set (newValue) {
        this.handleTabChange(newValue)
      }
    }
  },
  data () {
    return {
      editableTabsValue: this.$store.state.title
    }
  },
  mounted () {
    console.log(this.$store.state.title)
  },
  methods: {
    ...mapMutations(['SET_ACTIVE_TAB']),
    handleTabChange (tab) {
      this.SET_ACTIVE_TAB(tab)
    },
    rem (e) {
      this.$store.commit('remove', e)
    }
  }
}
</script>
<style scoped>
</style>

在写vuex代码前先安装一个vuex数据状态持久化-vuex-persistedstate插件来实现刷新页面数据还存在

我这里是直接用的总仓库来写的

vuex里的代码store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex)
export default new Vuex.Store({
  state: {
    tree: [
      {
        path: 'vv',
        name: '首页',
        func_fid: 0,
        id: '1000',
        children: [
          {
            path: 'sy',
            name: '首页儿子',
            func_fid: 1000,
            id: '1212'
          }
        ]
      },
      {
        path: 'hh',
        name: '系统管理',
        func_fid: 0,
        id: '1',
        children: [
          {
            id: '1-1',
            func_fid: 1,
            path: 'son1',
            name: '系统管理儿子'
          },
          {
            id: '2',
            func_fid: 1,
            path: 'hhh',
            name: '系统管理-角色',
            children: [
              {
                id: '222',
                func_fid: 1,
                path: 'son1-1-1',
                name: '角色管理',
                children: [
                  {
                    id: '12',
                    func_fid: 2,
                    path: 'son1-1-1',
                    name: '角色管理儿子',
                    children: [
                      {
                        id: '122',
                        func_fid: 2,
                        path: 'son1-1-1-1',
                        name: '角色管理儿子-----孙子'
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            id: '122',
            path: 'son1-2',
            name: '用户管理'
          }
        ]
      },
      {
        path: 'ss',
        name: '教学管理',
        id: '22',
        func_fid: 0,
        children: [
          {
            path: 'son2',
            name: '教学管理儿子',
            id: '202',
            func_fid: 22
          }
        ]
      },
      {
        path: 'zz',
        name: '行政管理',
        id: '3',
        func_fid: 0,
        children: [
          {
            path: 'son3',
            name: '行政管理儿子',
            id: '33',
            func_fid: 3
          }
        ]
      },
      {
        path: 'cv',
        name: '测试管理',
        id: '4',
        func_fid: 0,
        children: []
      }
    ],
    tabs: [],
    tabOne: [],
    title: ''
  },
  getters: {
  },
  mutations: {
    tab (state, payload) {
      function recursion (t) {
        state.tabs.push(t)
        if (t.children && t.children.length > 0) {
          for (let i = 0; i < t.children.length; i++) {
            recursion(t.children[i])
          }
        }
      }
      state.tree.forEach(item => {
        recursion(item)
      })
      state.tabs.forEach(item => {
        if (item.path === payload) {
          const ind = state.tabOne.findIndex(i => i.path === item.path)
          state.title = item.path
          if (ind === -1) {
            state.tabOne.push(item)
          }
        }
      })
    },
    SET_ACTIVE_TAB (state, newValue) {
      state.title = newValue
    },
    remove (state, payload) {
      console.log(payload)
      const i = state.tabOne.findIndex(item => item.path === payload)
      if (payload !== state.title) {
        console.log(payload)
      } else if (state.tabOne.length === 1) {
        state.title = ''
      } else if (i === state.tabOne.length - 1) {
        state.title = state.tabOne[i - 1].path
      } else {
        state.title = state.tabOne[i + 1].path
      }
      state.tabOne.splice(i, 1)
    }
  },
  actions: {
  },
  modules: {
  },
  plugins: [createPersistedState({
    storage: window.sessionStorage
  })]
})

这个是我的git仓库地址有需要的可以自行拉取

https://gitee.com/Flechazo7/vue2.git

路由代码

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
  {
    path: '/',
    name: 'home',
    component: () => import('../views/home/home.vue'),
    children: [
      {
        path: '',
        components: {
          son1: () => import('../views/home/son/sonOne.vue'),
          son2: () => import('../views/home/son/sonTwo.vue'),
          son3: () => import('../views/home/son/sonThree.vue')
        }
      }
    ]
  }
]
const router = new VueRouter({
  mode: 'hash',
  base: process.env.BASE_URL,
  routes
})
export default router
目录
相关文章
|
19天前
|
JavaScript
【vue】如何跳转路由到指定页面位置
【vue】如何跳转路由到指定页面位置
22 0
|
19天前
|
JavaScript
vue路由导航守卫(全局守卫、路由独享守卫、组件内守卫)
vue路由导航守卫(全局守卫、路由独享守卫、组件内守卫)
54 0
|
19天前
|
资源调度 JavaScript 前端开发
Vue的路由管理:VueRouter的配置和使用
【4月更文挑战第24天】VueRouter是Vue.js的官方路由管理器,用于在单页面应用中管理URL路径与组件的映射。通过安装并引入VueRouter,设置路由规则和创建router实例,可以实现不同路径下显示不同组件。主要组件包括:`&lt;router-link&gt;`用于创建导航链接,`&lt;router-view&gt;`负责渲染当前路由对应的组件。此外,VueRouter还支持编程式导航和各种高级特性,如嵌套路由、路由参数和守卫,以应对复杂路由场景。
|
19天前
|
JavaScript 数据可视化 算法
vue3+threejs可视化项目——搭建vue3+ts+antd路由布局(第一步)
vue3+threejs可视化项目——搭建vue3+ts+antd路由布局(第一步)
44 6
|
3天前
|
JavaScript 程序员 网络架构
vue路由从入门到进阶 --- 声明式导航详细教程
vue路由从入门到进阶 --- 声明式导航详细教程
vue路由从入门到进阶 --- 声明式导航详细教程
|
3天前
|
资源调度 JavaScript UED
vue路由的基础知识总结,vueRouter插件的安装与使用
vue路由的基础知识总结,vueRouter插件的安装与使用
|
10天前
|
缓存 JavaScript
一文彻底学会Vue路由
Vue Router简介,包括基本使用、嵌套路由、参数传递和路由守卫。首先,通过`npm i vue-router@3`安装,然后在`main.js`引入并应用。配置路由时,创建VueRouter实例,定义如`/home`、`/about`等路径及其对应组件。使用`&lt;router-link&gt;`进行切换,`&lt;router-view&gt;`展示组件。嵌套路由通过`children`配置多级路径,参数传递可使用`query`或`params`。路由守卫分为全局、独享和组件内三种,用于控制访问权限。
21 1
一文彻底学会Vue路由
|
18天前
|
资源调度 JavaScript 前端开发
阿珊详解Vue路由的两种模式:hash模式与history模式
阿珊详解Vue路由的两种模式:hash模式与history模式
|
19天前
|
JavaScript
vue中watch监听路由传来的参数变化问题
vue中watch监听路由传来的参数变化问题
12 0
|
19天前
|
缓存 JavaScript
在 Vue 组件中使用计算属性和侦听器来响应路由变化
【5月更文挑战第8天】Vue Router 中,计算属性和侦听器常用于根据路由变化更新组件状态。计算属性缓存依赖,当路由参数改变时自动更新,如示例中的 `userId`。侦听器则监听 `$route` 变化,执行相应操作,例如在 `currentUserId` 示例中响应 `userId` 更新。计算属性适合简单变化,而异步操作或复杂场景可选用侦听器。Vue 3 中,`watchEffect` 减少了部分侦听场景的复杂性。总之,它们用于组件内部响应路由变化,而非直接处理路由逻辑。
20 4