實現功能:點擊mean的子菜單,tabs顯示子菜單名稱。並且可以進行刪除,刷新之后,停留在刷新前的界面。
使用到的組件el-menu ,el-tabs。
使用到的工具:vue-router,vuex
實現效果:
項目目錄:
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