作者:一名 Vue 的学习者
记录时间:2025年12月
目标:优化上一节实现的菜单,实现 选中菜单 高亮、激活,可折叠。效果图如下:

菜单折叠高亮
上一篇我已经把后台最基础的布局(头部 + 左侧菜单 + 内容区 + 页脚)搭建好了,但左侧菜单目前还是一个超级“简陋”的版本:
- 只有静态数据
- 点击后不会高亮
- 路由切换看不出当前在哪
- 菜单太宽时无法折叠
- 也不支持子菜单
所以这一篇我继续把 Sidebar 进行 “精装修”做得更像后台系统,将会实现:
- 高亮当前菜单项(根据路由自动匹配)
- 点击菜单后的激活状态
- 简单实现菜单折叠(Collapse)
- 布局自适应折叠宽度
- 为后面动态菜单奠定基础
1. 让菜单能“知道”当前在哪个页面
Vue3 + Vue Router 的组合超级友善,我可以通过 useRoute 获取当前路由对象,通过它的 path 来判断是否选中。
先到 Sidebar 使用 route 信息
Sidebar.vue
<script setup>
import { useRouter, useRoute } from "vue-router";
const router = useRouter();
const route = useRoute();
const menus = [
{ title: "首页", path: "/" },
{ title: "用户管理", path: "/user" },
{ title: "系统设置", path: "/setting" }
];
function go(path) {
router.push(path);
}
</script>
在模板中判断是否高亮
<div
class="menu-item"
:class="{ active: route.path === item.path }"
v-for="item in menus"
:key="item.path"
@click="go(item.path)"
>
{{ item.title }}
</div>
给 active 加上样式
.menu-item.active {
background: #e0ecff;
color: #2d8cf0;
font-weight: bold;
}
至此,左侧菜单已经能“随着路由变化自动高亮”。
2. 实现菜单折叠(Collapse)
折叠菜单几乎是后台标配,我想实现一个简单版本:
- 点击按钮后,菜单从 200px → 60px
- 只显示图标,不显示文字(本篇先不做图标,但结构要预留)
- 内容区自动拉伸
为了实现折叠,我先在 Sidebar 的父级 Layout 中放一个“折叠按钮”。
2.1 在 Header 加一个折叠按钮
Header.vue
<template>
<div class="layout-header">
<div class="logo">
My Admin
<button class="collapse-btn" @click="$emit('toggleMenu')">
≡
</button>
</div>
<div class="right">
<span class="user">Hello, User</span>
<button class="logout">退出</button>
</div>
</div>
</template>
<style scoped>
.collapse-btn {
margin-left: 20px;
background: none;
border: none;
color: #fff;
cursor: pointer;
font-size: 22px;
}
</style>
2.2 在 Layout 中接收折叠事件
layout/index.vue
<script setup>
import { ref } from "vue";
import Header from "./Header.vue";
import Sidebar from "./Sidebar.vue";
import Footer from "./Footer.vue";
const collapsed = ref(false);
function toggleMenu() {
collapsed.value = !collapsed.value;
}
</script>
<template>
<div class="layout-container">
<Header @toggleMenu="toggleMenu" />
<div class="layout-body">
<Sidebar :collapsed="collapsed" />
<div class="layout-content">
<router-view />
</div>
</div>
<Footer />
</div>
</template>
让 Sidebar 接收 collapsed 状态。
2.3 Sidebar 根据 collapsed 调整宽度
Sidebar.vue
<template>
<div
class="layout-sidebar"
:style="{ width: collapsed ? '60px' : '200px' }"
>
<div
class="menu-item"
:class="{ active: route.path === item.path }"
v-for="item in menus"
:key="item.path"
@click="go(item.path)"
>
<!-- 文字折叠时隐藏 -->
<span v-if="!collapsed">{{ item.title }}</span>
</div>
</div>
</template>
<script setup>
const props = defineProps({
collapsed: Boolean
});
</script>
折叠相关样式优化
.layout-sidebar {
background: #f7f7f7;
height: calc(100vh - 56px - 40px);
transition: width 0.2s; /* 动画效果 */
}
.menu-item {
padding: 12px 20px;
cursor: pointer;
white-space: nowrap;
}
折叠后,菜单变窄,但仍能正常点击,也预留了图标空间,让后续扩展更容易。
3. 路由变动时菜单自动更新高亮
之前已经用 route.path 做了高亮,但我想进一步优化:
- 若后来菜单有二级路径 /user/list /user/info
- 我希望 /user 对应的一级菜单自动激活
因此我改成:
:class="{ active: route.path.startsWith(item.path) }"
这样即使进入 /user/detail?id=1 菜单也会正确激活。
4. 给菜单激活项增加视觉效果
我做了两件小改动:
① 左侧加高亮条
.menu-item.active {
background: #eaf2ff;
color: #2d8cf0;
font-weight: bold;
border-left: 3px solid #2d8cf0;
}
② hover 效果更柔和
.menu-item:hover {
background: #f1f1f1;
}
菜单变得更有后台“质感”了。
5. 小结:Sidebar 功能越来越像样了
这一篇我让左侧菜单比之前更“后台系统化”,主要做了三件事:
✔ 1. 当前路由自动高亮:通过 route.path 判断激活状态,切页后高亮同步更新。
✔ 2. 菜单折叠:菜单从 200px → 60px,折叠/展开带动画,布局自适应。
✔ 3. 更逼真的视觉效果:高亮条、柔和的 hover、隐藏文字。
这些都是后台系统侧边栏最基础也最必要的功能,随着菜单功能越来越完善,后续还将增加:
- 支持二级、三级菜单 和 多级菜单
- 增加菜单图标
- 使用element-plus框架优化菜单和布局
- 增加模拟登录页 + 真实后端请求登录
- 动态路由 + 后端返回菜单
- 权限控制
- 菜单缓存、展开状态保持
这些我会在后续的章节继续完成。
下一步计划:增加多级菜单 和 图标,使用Element-plus库进行美化!
© 版权声明
文章版权归作者所有,未经允许请勿转载。如内容涉嫌侵权,请在本页底部进入<联系我们>进行举报投诉!
THE END














暂无评论内容