{T}

ThemeSettings 导航模式卡片与样式细化

概述

主题设置面板搭好抽屉与表单骨架后,真正的产品化分水岭是「导航模式」这类配置项。它不再是普通开关,而是直接影响后台布局形态的布局级选择,因此更适合用可视化缩略卡片表达。本节把导航模式从文本配置升级为卡片选择器,并处理卡片作为状态块的视觉层级、FormItem 纵向化、缩略图用色块模拟、共享样式抽象与圆角裁切,最终完成 ThemeSettings 的样式面板阶段。

学习目标

  • 识别导航模式等「布局级配置」,用可视化卡片而非文本下拉表达布局差异
  • Tooltip + 卡片 组合降低用户理解成本,并让卡片具备默认 / hover / active 视觉层级
  • 对该 FormItem 改用纵向布局,避免模式卡片与横向 label 挤在一起
  • 用普通色块与绝对定位模拟布局缩略图,避免引入额外绘图资源
  • 把重复卡片样式抽成共享类,并注意父容器 relative + overflow-hidden 的圆角裁切

一、导航模式:从文本配置升级为可视化卡片

ThemeSettings 里大多数配置(Logo 显示、菜单宽度、主题色、暗黑模式)仍是挂在统一 form 上的标准表单项,复杂度主要在组织而非控件本身。但导航模式不同——它切换的是左侧菜单、顶部菜单或混合布局的整体形态,属于前一节说的「布局级配置」。如果只用普通下拉框或单选按钮,用户很难直观理解 sidebar / top / mix / dual-sidebar 的差异,而可视化小卡片能让布局区别一眼可见。课程口述里出现过 mixTopmixedBar 这类阶段性命名,项目里更推荐最终收口成与布局系统一致的稳定枚举。

二、卡片即状态块:视觉层级与 FormItem 纵向化

导航模式卡片不是普通按钮,而是「代表布局预览的状态块」:交互重点不在文字,而在当前是否选中、预览图是否清晰、hover / active 边框是否明显。它至少需要四层视觉状态:默认背景、hover 反馈、active 边框、必要时轻微阴影或浅边框。

这类卡片接入后,FormItem 的内部布局要从「左 label 右控件」的横向结构改成「label 在上、卡片在下」的纵向结构。继续沿用普通表单项横向布局,四个卡片会非常拥挤、不利于展示。规律是:开关、颜色、滑块适合横向表单项,卡片选择、模式预览适合纵向表单项。

三、缩略图用色块模拟而非绘制

课程实现四种导航模式缩略图时,没有上 SVG 或复杂图形,而是继续用 div + 背景色块 + 绝对定位 + 宽高比例来模拟侧边栏、顶部栏、内容区的关系:

Vue SFC
<div class="mode-item">
  <div class="absolute left-0 top-0 z-30 h-full w-1/4 bg-gray-900" />
  <div class="absolute left-1/4 top-0 z-10 h-full w-3/4 bg-white" />
</div>

深色块表达菜单、浅色块表达内容区,通过比例关系就能模拟「左侧菜单 + 右侧内容」的预览。实现 mixTop 可加顶部横条再补左侧窄菜单,top 把深色块放顶部横向,dual-sidebar 拆成两列深浅不同的左侧区域——不依赖额外图标素材,改颜色比例也方便。配合 el-tooltip 在 hover 时给出模式说明文字,是比纯文本单选更自然的交互:默认界面保持简洁,移上去再补语义。

四、共享样式抽象与圆角裁切

四个模式块的外层样式(圆角、背景、边框、尺寸)几乎一样,应尽早抽成共享类(如 .mode-item)统一复用,避免同一视觉卡片重复写多遍、后续改尺寸颜色时到处改。课程里把卡片从偏大的正方形收成更扁的矩形,更接近真实后台布局缩略图比例。

圆角能否生效有个典型细节:内部子元素用了 absolute 铺满,若父元素有圆角却不隐藏溢出,内部色块会把圆角「冲破」。规律几乎是固定的——父级有圆角、子级又要绝对定位铺满时,overflow-hidden 是标配:

css
.mode-item {
  @apply relative overflow-hidden rounded bg-gray-100 shadow-sm;
  @apply w-12 h-8 cursor-pointer border border-gray-200;
}
.mode-item.active {
  @apply border-2 border-blue-900;
}

五、样式面板收尾与联动预告

这一节让 ThemeSettings 的气质发生了变化:从「能弹出、能显示几个控件」变成「有结构层次、有模式卡片、有 hover 说明、有 active 反馈」,更接近真实后台产品的设置面板。但样式也不是终点——面板里的配置值如何真正驱动外层 DefaultLayout 才是下一阶段的重量级难点:

  • navMode 要切换菜单结构
  • menuWidth 要影响侧边栏宽度
  • showLogo 要影响布局展示
  • 主题色、菜单背景要与 Header / 菜单样式同步

到本节为止,ThemeSettings 已具备「可展示、可选择、可输入」的样式面板能力,下一步进入配置联动阶段。

六、数据驱动渲染:抽出配置数组

四种模式的卡片结构高度一致,逐个手写 mode-item + tooltip 会带来大量重复 DOM,且新增模式要改模板。更好的做法是把模式定义抽成配置数组,再用 v-for 渲染:

ts
const navModeOptions = [
  { value: "sidebar", label: "左侧菜单", desc: "经典侧边栏布局" },
  { value: "top", label: "顶部菜单", desc: "顶部横向导航" },
  { value: "mixTop", label: "混合顶部", desc: "顶部一级 + 左侧二级" },
  { value: "mixedBar", label: "混合栏", desc: "双列侧边菜单" }
]
Vue SFC
<div class="flex gap-3">
  <el-tooltip
    v-for="item in navModeOptions"
    :key="item.value"
    :content="item.desc"
    placement="top"
  >
    <div
      class="mode-item"
      :class="{ active: form.navMode === item.value }"
      @click="form.navMode = item.value"
    >
      <span class="mode-thumb" :data-mode="item.value" />
    </div>
  </el-tooltip>
</div>

数组化之后,选中态判断、Tooltip 文案、缩略图类型都来自同一份数据,维护和扩展成本显著下降。

七、navMode 枚举与布局结构映射

每个 navMode 值并不是孤立字符串,它背后对应着布局层的真实结构变化。提前把它们映射清楚,下一节的配置回传才不会「改了值却不知道布局怎么动」:

navMode菜单位置头部内容内容区
sidebar左侧完整菜单仅工具区右侧自适应
top收起,菜单上移头部横向菜单 + 工具区下方整块
mixTop顶部一级 + 左侧二级顶部一级导航左侧二级 + 内容
mixedBar双列侧边(一级窄、二级宽)工具区右侧内容

这一映射关系,也是后续 DefaultLayout 根据 navMode 切换组件结构、决定 SidebarHeader 各自渲染内容的依据。


常见问题

问题原因解决方案
导航模式用文字单选看不懂区别抽象模式缺直观表达用缩略卡片 + Tooltip 让布局差异可视化
模式卡片与 label 挤在一行沿用普通表单项横向布局该 FormItem 改纵向,label 在上卡片在下
卡片圆角不生效内部绝对定位色块溢出父容器父容器同时设 relativeoverflow-hidden
四种卡片样式越来越难改没抽共享类统一 .mode-item 等类复用
正方形卡片不像布局缩略图高宽比例过大显「厚」收成扁矩形,补轻微阴影浅边框
DOM 结构越写越重复直接复制卡片与 TooltipnavModeOptions 配置数组配合 v-for

延伸阅读