实现功能:点击mean的子菜单,tabs显示子菜单名称。并且可以进行删除,刷新之后,停留在刷新前的界面。

使用到的组件el-menu el-tabs

使用到的工具:vue-routervuex

实现效果:

 

项目目录:

 

App.vue

<template>
  <div id="app">
    <el-container>
      <el-aside width="300px">
        <Home></Home>
        <!-- 我是侧边栏 -->
      </el-aside>
      <el-container>
        <el-main>
          <tabs></tabs>
          <!-- 我是tabs组件 -->
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
import Home from '../src/views/Home'
import tabs from '../src/views/tabs'
export default {
  components:{
    Home,
    tabs
  }
}
</script>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* text-align: center; */
  color: #2c3e50;
}

#nav {
  padding: 30px;
}

#nav a {
  font-weight: bold;
  color: #2c3e50;
}

#nav a.router-link-exact-active {
  color: #42b983;
}
</style>

tabs.vue

<template>
  <div class>
    <el-tabs
      v-model="editableTabsValue"
      type="card"
      closable
      @tab-remove="removeTab"
      @tab-click="tabClick($event)"
    >
      <el-tab-pane
        :key="item.name"
        v-for="item in editableTabs"
        :label="item.title"
        :name="item.name"
      ></el-tab-pane>
    </el-tabs>
    <router-view />
  </div>
</template>

<script>
export default {
  name: "",
  components: {},
  data() {
    return {};
  },
  mounted() {
    //刷新加载sessionStorage存着地址
    if (sessionStorage.getItem("tabsPage")) {
      this.$store.state.tabsPage = JSON.parse(
        sessionStorage.getItem("tabsPage")
      );
      var TabsValue = sessionStorage.getItem("TabsValue");
      this.$store.state.TabsValue = TabsValue;
      if (sessionStorage.getItem("tabsPage") === "[]") {
        this.$router.push({ name: "Home" });
      } else {
        this.$router.push({ name: TabsValue });
      }
    }
  },
  computed: {
    // 监听vuex保存的数据
    editableTabs: {
      get() {
        return this.$store.state.tabsPage;
      },
      set(val) {
        this.$store.state.tabsPage = val;
      },
    },
    editableTabsValue: {
      get() {
        return this.$store.state.TabsValue;
      },
      set(val) {
        this.$store.state.TabsValue = val;
      },
    },
  },
  methods: {
    removeTab(targetName) {
      let tabs = this.editableTabs;
      let activeName = this.editableTabsValue;
      if (activeName === targetName) {
        tabs.forEach((tab, index) => {
          if (tab.name === targetName) {
            let nextTab = tabs[index + 1] || tabs[index - 1];
            console.log(nextTab);
            if (nextTab) {
              activeName = nextTab.name;
            }
          }
        });
      }
      this.editableTabsValue = activeName;
      this.editableTabs = tabs.filter((tab) => tab.name !== targetName);
      this.$store.state.tabsPage = this.editableTabs;
      window.sessionStorage.tabsPage = JSON.stringify(this.editableTabs);
      //解决刷新消失
      window.sessionStorage.setItem("TabsValue", activeName);
      // 删除时跳转不在停留被删除页
      if (sessionStorage.getItem("tabsPage") === "[]") {
        this.$router.push({ name: "home" });
      } else {
        this.$router.push({ name: activeName });
      }
    },
    tabClick(event) {
      //写一个点击tabs跳转
      this.$router.push({ name: event.name });
    },
  },
};
</script>

Home.vue

<style lang="less" scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
  min-height: 97.3vh;
  width: 14rem;
}
.el-menu {
  padding-top: 2.7vh;
}
.el-submenu__title i,
.el-menu-item i {
  color: #909399;
  position: relative;
  right: 0.4rem;
  font-size: 12px;
}
.el-menu-item {
  min-width: auto !important;
}
.el-submenu /deep/ .el-submenu__title .el-submenu__icon-arrow {
  position: absolute;
  right: 2rem;
}
</style>
<template>
  <div class="height:100%">
      <!--
        :default-active="$route.name" 
        获取router路由的name 对应menu-item内的index
        为了对应 tabs 的跳转点击 做选中
      -->
      <el-menu
        :default-active="$route.name"
        class="el-menu-vertical-demo"
        background-color="#545c64"
        text-color="white"
        active-text-color="#ffd04b"
      >
        <!-- 循环数据格式 -->
        <el-submenu :index="`${index}`" v-for="(menu,index) in menuList" :key="index">
          <template slot="title">
            <i :class="menu.icont"></i>
            <span>{{menu.name}}</span>
          </template>
          <el-menu-item-group>
            <el-menu-item
              :index="item.routeName"
              v-for="item in menu.menuItem"
              :key="item.index"
              @click="handleOpen2(item)"
            >{{item.name}}</el-menu-item>
          </el-menu-item-group>
        </el-submenu>
      </el-menu>
    </div>
</template>

<script>
import { mapActions } from "vuex";
export default {
  name: "zgz-admin-index-aside",
  components: {},
  data() {
    return {
      // 将所需submenu,menu和tabs所需参数写成数据格式
      menuList: [
        {
          icont: "el-icon-s-tools",
          name: "子菜单",
          menuItem: [
            {
              title: "子菜单1",
              routeName: "Setting",
              name: "子菜单1",
            },
            {
              title: "子菜单2",
              routeName: "WxAd",
              name: "子菜单2",
            },
          ],
        },
        {
          icont: "el-icon-s-tools",
          name: "子菜单呀",
          menuItem: [
            {
              title: "子菜单呀1",
              routeName: "Setting",
              name: "子菜单呀1",
            },
            {
              title: "子菜单呀2",
              routeName: "WxAd",
              name: "子菜单呀2",
            },
          ],
        },
        {
          icont: "el-icon-s-order",
          name: "子菜单啊呀",
          menuItem: [
            {
              title: "子菜单啊呀1",
              routeName: "orderList",
              name: "子菜单啊呀1",
            },
            {
              title: "子菜单啊呀2",
              routeName: "orderList",
              name: "子菜单啊呀2",
            },
          ],
        },
      ],
    };
  },
  created() {},
  mounted() {},
  methods: {
    // 调用 注册vuex内注册的editableTabs方法
    ...mapActions({
      handleOpen2: "editableTabs",
    }),
  },
};
</script>

store中的index.js

import Vue from 'vue';
import Vuex from 'vuex';
// 引入 router 在vuex内使用router跳转
import router from '../router';

Vue.use(Vuex);
Vue.use(router);

export default new Vuex.Store({
  state: { // 定义tabs 所需参数
    tabsPage: [],
    TabsValue: ''
  },
  mutations: {
    editableTabs: (state, obj) => {
      // 浅拷贝 state.tabsPage
      const arr = Array.from(state.tabsPage)
      // 判断数组内是否为空
      if (arr.length !== 0) {
        // 使用 Array.some 去判断是否存在对象信息
        var even = function (obj) {
          return arr.some(item => {
            return item.name === obj.routeName
          })
        }
        // even方法 如果对象存在返回true,不存在则返回flase
        // 加!触发 true 代码块
        if (!even(obj)/* 如果不存在将对象push进数组内bing */) {
          // 将tabs所需参数push进arr数组
          arr.push({ title: obj.name, name: obj.routeName })
          // 赋值给tabsPage参数
          state.tabsPage = arr
          // 存储sessionStorage -- 解决刷新消失
          window.sessionStorage.setItem('tabsPage', JSON.stringify(arr))
          window.sessionStorage.setItem('TabsValue', obj.routeName)
          // 赋值给TabsValue参数
          state.TabsValue = obj.routeName
          // 跳转
          router.push({ name: obj.routeName })
        } else { // 如果存在 只做跳转选中
          // 赋值给TabsValue参数
          state.TabsValue = obj.routeName
          window.sessionStorage.setItem('TabsValue', obj.routeName)
          // 跳转
          router.push({ name: obj.routeName })
        }
      } else { // 如果为0
        // 将tabs所需参数push进arr数组
        arr.push({
          title: obj.name, name: obj.routeName
        })
        // 赋值给tabsPage参数
        state.tabsPage = arr
        // 赋值给TabsValue参数
        state.TabsValue = obj.routeName
        // 跳转
        router.push({ name: obj.routeName })
      }
    }
  },
  actions: {
    // 注册方法
    editableTabs(context, obj) {
      context.commit('editableTabs', obj)
    }
  }
})

router中的index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Setting from '../views/Setting.vue'
import WxAd from '../views/WxAd.vue'
import orderList from '../views/orderList.vue'


Vue.use(VueRouter)
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function (location, onResolve, onReject) {
  if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
  return originalPush.call(this, location).catch(err => err)
}

const routes = [
  {
    path: '/home',
    name: 'Home',
  },
  {
    path: '/Setting',
    name: 'Setting',
    component: Setting
  },
  {
    path: '/WxAd',
    name: 'WxAd',
    component: WxAd
  },
  {
    path: '/orderList',
    name: 'orderList',
    component: orderList
  }
]

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

export default router
posted on 2020-08-25 14:18  小名香菜~  阅读(3135)  评论(0编辑  收藏  举报