使用vue+element-ui实现侧边栏菜单
el-menu
与el-tabs
标签页联动效果
先看实现效果
el-menu
使用vue-router
的模式,以index进行路由跳转,当前激活菜单:default-active="$route.path"
,这样就会默认以当前路由路径高亮菜单选项,解决刷新等情况的高亮问题,主要代码<el-menu:default-active="$route.path"class="el-menu-vertical-demo" background-color="#2f3640" text-color="#fff":style="{width:asideBarWidth}":width="asideBarWidth":collapse="$store.state.isCollapse":unique-opened="true":router="true" active-text-color="#409EFF"><menu-item v-for="item in menuData":key="item.path":item="item"/></el-menu>
el-tabs
的:value
(选中选项卡的name
)也是由$route.path
进行控制,el-tabs
的数据结构是这样的:[{title: '首页',path: '/home',name: 'Home'}]
(vuex管理),当点击的通过path进行路由跳转,删除时,如果是删除当前页,则需要获取下一个标签页的路径,再进行跳转。<template><el-tabs type="card":value="$route.path" @tab-click="tabClick" closableclass="my-tabs" @edit="handleTabsEdit"><el-tab-pane:key="item.path" v-for="(item) in tabsValue":label="item.title":name="item.path"></el-tab-pane></el-tabs></template><script>import{ mapState}from'vuex'import{ setSessionTabsValue}from'@/utils/storage'exportdefault{ name:'TabsNav',data(){return{}},created(){}, watch:{},mounted(){// 监听刷新,将数据保存到sessionStorage里 window.addEventListener('beforeunload',this.setStorage)},destroyed(){ window.removeEventListener('beforeunload',this.setStorage)}, computed:{...mapState({ tabsValue: state=> state.tabsNav.tabsValue})}, methods:{setStorage(){ console.log('setStorage')setSessionTabsValue(this.tabsValue)},handleTabsEdit(targetPath, action){// 删除选项卡if(action==='remove'){if(targetPath==='/home')returnlet nextTab={}// 找到下一个路由this.tabsValue.forEach((item, index)=>{if(item.path=== targetPath){ nextTab=this.tabsValue[index+1]||this.tabsValue[index-1]}})this.$store.commit('REMOVE_TABS_VALUE', targetPath)// 如果删除的是当前页,则进行跳转 targetPath===this.$route.path&&this.$router.push(nextTab.path)}},tabClick({ name}){if(name===this.$route.path)returnthis.$router.push(name)}}}</script>
vuex
管理标签页的状态import{ getSessionTabsValue}from'@/utils/storage'// 初始化const initTabValue=getSessionTabsValue()||{ tabsValue:[{ title:'首页', path:'/home', name:'Home'}]}const tabsNav={ state:()=>(initTabValue), mutations:{/** * 删除标签页 * @param {*} state * @param {*} targetPath */REMOVE_TABS_VALUE(state, targetPath){ state.tabsValue= state.tabsValue.filter(item=> item.path!== targetPath)},/** * 添加标签页,在MenuItem组件触发 * @param {*} state * @param {*} data */ADD_TABS_VALUE(state, data){// 判断是否已经存在const isExist= state.tabsValue.some(item=> item.path=== data.path)// 如果不存在添加if(!isExist){ state.tabsValue.push(data)}},/** * 初始化数据,在注销时调用,不然切换用户后还是旧标签数据 * @param {*} state */RESET_TABS_VALUE(state){ state= initTabValue}}, actions:{}, getters:{}}exportdefault tabsNav
tabsValue
(在mutations的ADD_TABS_VALUE判断)// 路由对象数据结构{ path:'/home', name:'Home', component: Home, meta:{ title:'首页', isTabsPage:true}} router.beforeEach((to,from, next)=>{if(to.meta.title){// 如果设置标题,拦截后设置标题 document.title= to.meta.title}if(to.path!=='/login'){if(!store.getters.isLogin){ Message.error('请先登录')next('/login')return}// 判断是否需要添加到tabs标签if(to.meta.isTabsPage){const tabsItem={ name: to.name, title: to.meta.title, path: to.path} store.commit('ADD_TABS_VALUE', tabsItem)}}next()})
keep-alive
对在标签页的页面进行缓存<el-main><transition name="fade-transform" mode="out-in"><keep-alive:include="cachedViews"><router-view></router-view></keep-alive></transition></el-main>cachedViews(){returnthis.$store.state.tabsNav.tabsValue.map(item=> item.name)}
这样就实现了上面的效果,但是还有许多地方可以优化,并且耦合性有点高…