使用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)}
这样就实现了上面的效果,但是还有许多地方可以优化,并且耦合性有点高…