默认布局:菜单模式切换及折叠效果设计
菜单的折叠(collapse)功能是管理后台的标配。Element Plus 的 el-menu 组件原生支持 collapse 属性,但在实际项目中,折叠状态需要从 Header 的折叠按钮控制,传递到 Layout 的侧栏宽度调整,再到 Menu 组件的 collapse 绑定——这是一个跨越多层组件的双向数据流。
collapse 的双向数据绑定
折叠状态使用 defineModel 实现父子组件间的双向绑定:
// header.vue
const collapseModel = defineModel<boolean>('collapse', {
default: false,
})
typescript
模板中折叠按钮的点击事件直接修改 model 值:
<Iconify
:icon="collapseModel ? 'ep:expand' : 'ep:fold'"
class="text-xl cursor-pointer"
@click="collapseModel = !collapseModel"
/>
vue
在 DefaultLayout 中使用 v-model 绑定:
<Header v-model:collapse="localSettings.collapse" />
vue
这样当用户点击折叠按钮时,状态变更自动反映到 Layout,再传递给 Menu 组件。
Menu 组件的 collapse 绑定
<!-- default.vue -->
<Menu
:data="menus"
:collapse="localSettings.collapse"
:style="{ width: localSettings.collapse ? '64px' : `${localSettings.menuWidth}px` }"
/>
vue
折叠时菜单宽度从默认的 240px 缩小到 64px(只显示图标的宽度)。el-menu 的 collapse 属性会自动处理以下效果:
- 隐藏菜单项的文字
- 收起子菜单
- 隐藏
el-sub-menu的展开箭头 - 调整菜单项的内边距
ThemeSettings 中的折叠开关
在主题设置的 Drawer 中也可以控制折叠:
<el-form-item label="折叠菜单">
<el-switch v-model="form.collapse" />
</el-form-item>
vue
但这带来一个问题:ThemeSettings 中的 form.collapse 和 Header 的 collapseModel 可能不同步。解决方案是将两者都绑定到同一个数据源——localSettings.collapse。
侧栏宽度的过渡动画
折叠/展开时侧栏宽度变化需要添加过渡动画,避免突兀:
aside {
transition: width 0.3s ease;
}
css
在 Layout 组件中:
<aside
class="h-full transition-all duration-300"
:style="{ width: sidebarWidth }"
>
vue
transition-all duration-300(Tailwind 类)等价于 transition: all 0.3s ease。
菜单模式切换的联动
ThemeSettings 中的导航模式切换会影响 Layout 的整体结构。四种模式的差异在于菜单的位置和 Content 区域的布局:
sider 模式: mixed 模式: top 模式: mixedBar 模式:
┌──┬──────┐ ┌─────┬────┐ ┌────────────┐ ┌──┬──────┐
│ │ │ │ top │ │ │ menu │ │ │ │
│M │ │ ├─────┤ │ ├────────────┤ │M │ │
│E │ C │ │ M │ C │ │ │ │E │ C │
│N │ O │ │ E │ O │ │ C │ │N │ O │
│U │ N │ │ N │ N │ │ O │ │U │ N │
│ │ T │ │ U │ T │ │ N │ │ │ T │
└──┴──────┘ └─────┴────┘ └────────────┘ └──┴──────┘
text
模式切换的实现需要根据 settings.mode 动态调整 Layout 的结构,这通常通过 v-if 条件渲染不同的布局模板来实现。
本节小结
- defineModel:折叠状态使用
defineModel实现父子双向绑定,比 props + emit 更简洁。 - 宽度过渡:侧栏宽度变化通过
transition-all添加平滑动画。 - 状态同步:Header 的折叠按钮和 ThemeSettings 的折叠开关绑定到同一个数据源。
- 模式切换:四种导航模式通过条件渲染不同的布局结构实现。
↑