vue项目菜单激活

Vue3.0动态激活左侧菜单实现
本文介绍了如何在Vue3.0中动态激活左侧菜单。通过设置精确匹配类名,利用`router-link-active`和`router-link-exact-active`实现菜单高亮。但需注意,由于Vue3.0的改变,`router-link-active`不再适用于非嵌套路由的模糊匹配。示例代码展示了在`app-member-aside.vue`和`router/index.js`中的配置方法,包括个人中心和个人订单路由的设置。

目的:动态激活左侧菜单

大致步骤:

  • 添加个人中心路由地址,设置精准匹配类名
  • 添加我的订单路由与组件
router-link-active   当你的路由路径包含 router-link组件的to属性值,当前组件会加上它
router-link-exact-active   当你的路由路径完全和你的router-link组件的to属性值一致,当前组件会加上它

注意:vue3.0 router-link-active 加不上,路由路径包含 且 需要又路由嵌套关系。

  • 例如:/member /member/other 但是不是嵌套路由,不会加上这个类 router-link-active

src/components/app-member-aside.vue

      <h4>我的账户</h4>
      <div class="links">
+        <RouterLink to="/member" exact-active-class="active">个人中心</RouterLink>
        <a href="javascript:;">消息通知</a>
        <a href="javascript:;">个人信息</a>
        <a href="javascript:;">安全设置</a>
        <a href="javascript:;">地址管理</a>
        <a href="javascript:;">我的积分</a>
        <a href="javascript:;">我的足迹</a>
        <a href="javascript:;">邀请有礼</a>
        <a href="javascript:;">幸运抽奖</a>
      </div>
      <h4>交易管理</h4>
      <div class="links">
+        <RouterLink to="/member/order" exact-class="active">我的订单</RouterLink>
        <a href="javascript:;">优惠券</a>

src/router/index.js

const MemberOrder = () => import('@/views/member/order')
          {
            path: '/member/order/',
            // vue3.0 需要有嵌套关系才能模糊匹配    
            component: { render: () => h(<RouterView/>) },
            children: [
              { path: '', component: MemberOrder },
              { path: ':id', component: MemberOrderDetail }
            ]
          }

 

<think>根据用户需求,需要在Vue项目中实现一级菜单和二级菜单并列两列布局。参考提供的代码片段,用户已经有一个侧边栏组件(SideMenu)用于显示二级菜单,但当前布局是一级菜单在顶部(从代码中看,用户代码中一级菜单没有在顶部显示,而是将一级菜单的标题作为侧边栏的标题,二级菜单作为侧边栏的菜单项),而用户希望的是两列布局:一列显示一级菜单,另一列显示对应的二级菜单。分析用户提供的代码:-当前结构:整个页面分为`el-aside`(侧边栏)和`el-main`(主内容区)。侧边栏中放置了`SideMenu`组件,该组件接收一个`lists`属性,这个`lists`是一个数组,每个元素代表一个一级菜单,包含`title`(一级菜单标题)和`children`(二级菜单数组)。-当前效果:侧边栏中会显示多个一级菜单的标题及其下的二级菜单项。但这不是并列两列,而是将所有的一级菜单及其二级菜单都显示在同一个侧边栏中。用户需求:一级菜单和二级菜单并列两列。可以理解为:第一列:显示所有一级菜单的列表(通常是垂直排列)。第二列:当点击某个一级菜单,显示该一级菜单下的二级菜单列表。因此,我们需要调整布局:1.将一级菜单单独放在一列(比如左侧第一列),二级菜单放在相邻的第二列(左侧第二列),然后主内容区域在右侧。2.或者,一级菜单横向在顶部,二级菜单左侧侧边栏,但用户要求是两列,所以这里更可能是指左右两列:一级菜单一列,二级菜单一列。参考引用中的代码,用户之前已经将二级菜单放在侧边栏(`el-aside`)中,但一级菜单没有单独列出来。因此,我们需要修改布局,增加一个用于显示一级菜单的列。具体实现思路:-将页面布局改为三列:第一列(一级菜单)、第二列(二级菜单)、第三列(主内容区)。或者,如果二级菜单列和主内容区是同存在的,那么也可以将二级菜单列和主内容区放在一起作为第二列,但这样实际上是两列:一级菜单列和(二级菜单+主内容区)列。但用户要求是两列:一级菜单和二级菜单并列,所以这里我们可以将主内容区放在二级菜单列的下方?或者用户希望二级菜单列和主内容区是分开的?从用户提供的代码中,主内容区(`el-main`)是独立于侧边栏的,所以这里我们理解用户的需求是:左侧第一列:一级菜单左侧第二列:二级菜单(对应当前选中的一级菜单)右侧主内容区但是,用户问题中只提到了一级菜单和二级菜单并列两列,并没有提到主内容区。因此,我们可以将布局分为两部分:左侧:并列两列,第一列是一级菜单,第二列是二级菜单。右侧:主内容区。或者,另一种常见的布局是:顶部:可能是一些全局导航或标题左侧:一级菜单(垂直)->然后当点击一级菜单,在其右侧展开二级菜单(也是垂直),然后二级菜单的右侧是主内容区。根据用户提供的代码,他们使用了ElementUI的布局组件(el-aside,el-main)。我们可以这样设计:布局结构:<divclass="app-container"><!--顶部导航(如果有)--><el-header>...</el-header><divclass="main-layout"><!--第一列:一级菜单--><el-asideclass="first-level-menu"><!--这里显示一级菜单列表--></el-aside><!--第二列:二级菜单--><el-asideclass="second-level-menu"><!--这里显示当前一级菜单下的二级菜单列表--></el-aside><!--主内容区--><el-main><router-view></router-view></el-main></div></div>但是,注意用户提供的代码中,一级菜单数据是包含二级菜单的。因此,我们需要将一级菜单单独提取出来,作为第一列,然后当点击一级菜单,在第二列显示该一级菜单的二级菜单。步骤:1.拆分数据:我们有一级菜单数组,每个一级菜单项包含其二级菜单。2.在第一列(first-level-menu)中,使用v-for遍历一级菜单数组,显示一级菜单的标题。3.为一级菜单项添加点击事件,记录当前激活的一级菜单。4.在第二列(second-level-menu)中,根据当前激活的一级菜单,显示其二级菜单数组。同,我们还可以使用路由来控制,当点击二级菜单,在主内容区显示相应的组件。修改后的代码示例:注意:这里我们使用ElementUI的菜单组件来美化,但也可以使用简单的div。为了保持一致性,我们可以使用Element的菜单组件。由于用户已经有一个SideMenu组件(用于显示二级菜单),我们可以保留这个组件,并稍作调整。但是,根据用户提供的SideMenu组件的使用方式,它接收一个lists属性,这个lists是一个数组(包含多个一级菜单对象,每个对象有children)。而现在,我们需要在第二列只显示当前激活的一级菜单的children,所以可以修改SideMenu组件,使其只接收一个数组(即二级菜单数组),或者不修改组件,而是将当前激活的一级菜单的children作为属性传入(此SideMenu内部可能需要调整,因为它原本是遍历多个一级菜单的)。考虑到用户原有SideMenu组件可能是为多级菜单设计的,我们这里可以选择修改SideMenu组件使其更通用,或者创建一个新的组件。为了快速实现,我们这里不修改SideMenu组件,而是重新设计一个只显示二级菜单的组件,或者调整传入SideMenu的数据。但为了最小化改动,我们可以这样:将当前激活的一级菜单的children数组包装成一个新的数组,其结构为:[{title:当前激活的一级菜单的标题,children:当前激活的一级菜单的children}]然后传入SideMenu组件。这样SideMenu组件就会只显示一个一级菜单下的二级菜单。但是,这样SideMenu组件还是会显示一个标题(当前激活的一级菜单标题),然后下面列出二级菜单。这符合常规。因此,我们可以在第二列这样使用:<SideMenu:lists="currentMenuChildren"/>其中,currentMenuChildren是一个计算属性,返回一个数组,数组只有一个元素,即当前激活的一级菜单(包含title和children)。具体实现:模板部分:```html<template><divclass="system"><!--一级菜单列--><el-asideclass="first-level-aside"><divv-for="(menu,index)inmenus":key="index"@click="activateMenu(menu)">{{menu.title}}</div></el-aside><!--二级菜单列--><el-asideclass="second-level-aside"><SideMenu:lists="currentMenuChildren"/></el-aside><!--主内容区--><el-main><router-view></router-view></el-main></div></template>```脚本部分:```javascript<script>importSideMenufrom'@/components/sidemenu/SideMenu';exportdefault{components:{SideMenu},data(){return{activeMenuIndex:0,//当前激活的一级菜单索引,假设默认第一个menus:[//原始菜单数据{title:'菜单管理',children:[{index:'menuManage',title:'菜单管理'},{index:'contentManage',title:'内容管理'},{index:'roleManage',title:'角色管理'}]},{title:'系统管理',children:[{index:'systemManage',title:'系统设置'}]}]};},computed:{currentMenuChildren(){//将当前激活的一级菜单包装成SideMenu需要的数组格式if(this.menus.length>0){return[this.menus[this.activeMenuIndex]];}return[];}},methods:{activateMenu(menu){//找到菜单的索引constindex=this.menus.findIndex(item=>item===menu);if(index!==-1){this.activeMenuIndex=index;}}}};</script>```样式部分:需要设置两列的宽度,并让它们并排。可以使用flex布局。```html<stylescoped>.system{display:flex;height:100%;/*确保容器有高度*/}.first-level-aside{width:150px;/*一级菜单宽度*/background-color:#eef1f6;}.second-level-aside{width:200px;/*二级菜单宽度*/}.el-main{flex:1;/*主内容区占据剩余空间*/}</style>```注意:这里的一级菜单列我们使用了简单的div,没有使用菜单组件,可以根据需要使用ElementUI的菜单组件进行美化。使用ElementUI的菜单组件重写一级菜单列:```html<el-asideclass="first-level-aside"><el-menu:default-active="activeMenuIndex"background-color="#eef1f6"active-text-color="#ffd04b"><el-menu-itemv-for="(menu,index)inmenus":key="index":index="index.toString()"@click="activateMenu(menu,index)"><spanslot="title">{{menu.title}}</span></el-menu-item></el-menu></el-aside>```同,修改activateMenu方法,接收index参数,并设置activeMenuIndex为index。这样,一级菜单列就会以菜单的形式呈现,并且有高亮效果。以上代码实现了基本的两列菜单布局。用户可以根据实际需求调整样式和细节。注意:如果用户希望一级菜单点击后跳转,而不是展开二级菜单,那么需要根据需求调整。这里我们假设一级菜单的作用是展开其下的二级菜单。另外,二级菜单的SideMenu组件内部可能已经实现了路由跳转(根据index属性),所以主内容区会显示对应的组件。相关问题:1.如何实现三级菜单的嵌套?2.如何优化菜单的响应式设计?3.如何根据路由自动激活对应的菜单项?</think>在 Vue 项目中实现一级菜单和二级菜单并列两列布局,可以通过以下方案实现: ### 解决方案:使用 Flex 布局实现双列菜单 ```html <template> <div class="menu-container"> <!-- 一级菜单列 --> <div class="primary-menu"> <div v-for="(item, index) in menuData" :key="index" class="menu-item" :class="{ active: activeIndex === index }" @click="selectPrimaryMenu(index, item)" > {{ item.title }} </div> </div> <!-- 二级菜单列 --> <div class="secondary-menu"> <div v-for="(subItem, subIndex) in activeChildren" :key="subIndex" class="submenu-item" @click="selectSubMenu(subItem)" > {{ subItem.title }} </div> </div> </div> </template> <script> export default { data() { return { activeIndex: 0, // 当前激活的一级菜单索引 menuData: [ { title: '系统管理', children: [ { index: 'userManage', title: '用户管理' }, { index: 'roleManage', title: '角色管理' } ] }, { title: '内容管理', children: [ { index: 'articleManage', title: '文章管理' }, { index: 'commentManage', title: '评论管理' } ] } ] } }, computed: { // 当前激活菜单的子菜单 activeChildren() { return this.menuData[this.activeIndex]?.children || [] } }, methods: { selectPrimaryMenu(index, item) { this.activeIndex = index // 可添加路由跳转逻辑 // this.$router.push(item.children[0].index) }, selectSubMenu(item) { // 二级菜单点击处理 this.$router.push(item.index) } } } </script> <style scoped> .menu-container { display: flex; height: 100%; } .primary-menu { width: 150px; background: #f5f7fa; border-right: 1px solid #e6e6e6; } .secondary-menu { width: 180px; background: #fff; border-right: 1px solid #e6e6e6; } .menu-item, .submenu-item { padding: 12px 16px; cursor: pointer; transition: background 0.3s; } .menu-item:hover, .submenu-item:hover { background: #ecf5ff; } .menu-item.active { background: #409eff; color: white; } </style> ``` ### 实现要点说明 1. **布局结构**: - 使用 Flex 布局创建并列的两列 - 左侧 `primary-menu` 显示一级菜单(宽度建议 150-200px) - 右侧 `secondary-menu` 显示二级菜单(宽度建议 180-220px) 2. **数据驱动**: - `menuData` 存储嵌套菜单结构 - `activeIndex` 跟踪当前激活的一级菜单 - `activeChildren` 计算属性动态获取当前二级菜单 3. **交互逻辑**: - 点击一级菜单更新激活状态并显示对应二级菜单 - 点击二级菜单触发路由跳转(需配置 Vue Router) 4. **样式设计**: - 使用边框分隔双列菜单 - 激活状态高亮显示 - 悬停效果提升交互体验 ### 与 Element UI 集成方案 若使用 Element UI,可优化为: ```html <template> <el-row class="menu-container"> <el-col :span="4" class="primary-col"> <el-menu :default-active="activeIndex" background-color="#f5f7fa" > <el-menu-item v-for="(item, index) in menuData" :key="index" :index="index.toString()" @click="selectPrimaryMenu(index)" > <span>{{ item.title }}</span> </el-menu-item> </el-menu> </el-col> <el-col :span="5" class="secondary-col"> <el-menu> <el-menu-item v-for="(subItem, subIndex) in activeChildren" :key="subIndex" :index="subItem.index" @click="selectSubMenu(subItem)" > {{ subItem.title }} </el-menu-item> </el-menu> </el-col> </el-row> </template> ``` [^1] ### 响应式设计建议 添加媒体查询实现移动端适配: ```css @media (max-width: 768px) { .menu-container { flex-direction: column; } .primary-menu, .secondary-menu { width: 100%; } } ``` ### 路由集成示例 在 Vue Router 中配置嵌套路由: ```javascript const routes = [ { path: '/system', component: Layout, children: [ { path: 'user', component: UserManage }, { path: 'role', component: RoleManage } ] }, { path: '/content', component: Layout, children: [ { path: 'articles', component: ArticleManage }, { path: 'comments', component: CommentManage } ] } ] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值