vue-vben-admin 换肤实操:从改一个色值到明暗自动切换
【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. It's fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin
在 DevTools 里把--primary改成品牌色,保存后刷新页面,颜色又回去了——这是很多人第一次给 vue-vben-admin 换肤时的真实困惑。原因一句话点破:vben 的主题状态存在 preferences 里,每次启动都会重新写回 CSS 变量,你在控制台改的值只活了一瞬间。读完这篇,你能独立做到:新增一个内置主题、给业务组件加一套明暗自适应的自定义色变量,并拼出明暗 + 取色器的一键切换器。
先看效果
打开任意内置主题 + 切换暗色模式:登录页的侧边栏、卡片、按钮全部自动翻转;再选一个自定义主色,整套界面立刻换装。整个过程不写一行条件判断,只靠变量覆盖。
一张表看懂变量体系
CSS 变量(--xxx) | Less/SCSS 变量(@/$) | 混合场景 |
|---|---|---|
运行时可改,JS 一行setProperty就生效 | 编译时被静态替换成具体值,运行时改不了 | 组件用--primary,布局尺寸用 SCSS 变量 |
| 明暗切换全靠它:切属性 = 切一批值 | 只适合写死的间距、字号等稳定值 | 业务色必须走 CSS 变量 |
| 改完立即全局生效,适合"换肤" | 改完必须重新构建 | 混用时记住:能动态的就别用编译期变量 |
vue-vben-admin 的明暗切换就藏在两个文件里:亮色变量 和 暗色变量:
:root { --background: 0 0% 100%; --foreground: 210 6% 21%; } .dark, .dark[data-theme='custom'], .dark[data-theme='default'] { --background: 222.34deg 10.43% 12.27%; --foreground: 0 0% 95%; }切换时,偏好系统只做了两件事:给<html>加dark类,并设置data-theme属性,浏览器随后自动用新选择器里的值覆盖所有变量。CSS 变量是遥控器,SCSS 变量是出厂漆面——想随时换,就得装遥控器。
四个动手任务,由浅入深
🎨 任务一:给内置主题加一个主色
【改哪】packages/@core/preferences/src/constants.ts
【改什么】在BUILT_IN_THEME_PRESETS数组里追加一项:
{ color: 'hsl(174 65% 34%)', type: 'teal', },【看到什么】偏好面板"内置主题"里多一个色块。选中它后,document.documentElement.dataset.theme被写成teal,全部按钮、选中态、聚焦环一键换色。完整选择器写法见 暗色变量文件。
🌙 任务二:加一组业务变量 + 暗色分支
【改哪】packages/@core/base/design/src/design-tokens/default.css(亮色)+ 同名dark.css(暗色)
【改什么】注意 vben 的色值存的是 HSL 三元组,具体颜色由消费处的hsl(var(--xxx))拼出来:
:root { --business-primary: 243 84% 56%; --business-foreground: 0 0% 98%; } .dark { --business-primary: 243 90% 72%; --business-foreground: 0 0% 10%; }【看到什么】消费hsl(var(--business-primary))的卡片,切到暗色模式时自动变亮一档——你只写了两组值,切换逻辑是现成的。
⚡ 任务三:拼一个明暗 + ColorPicker 切换器
【改哪】任意业务组件,例如src/views/demos/theme-switcher.vue
【改什么】用 preferences 钩子读写主题(vben 早期版本里这套逻辑叫useDarkModeTheme/useRootSetting,现在统一收敛到usePreferences):
<script setup lang="ts"> import { usePreferences } from '@vben/preferences'; import { convertToHsl } from '@vben/utils'; const { getPreferences, updatePreferences } = usePreferences(); function toggleDark() { updatePreferences({ theme: { mode: getPreferences().theme.mode === 'dark' ? 'light' : 'dark' }, }); } function pickColor(e: Event) { const v = (e.target as HTMLInputElement).value; updatePreferences({ theme: { colorPrimary: convertToHsl(v) } }); } </script> <template> <div class="flex gap-3"> <button type="button" @click="toggleDark">切换明暗</button> <input type="color" value="#5B8DEF" @input="pickColor" /> </div> </template>【看到什么】点按钮,updateCSSVariables在 packages/@core/preferences/src/update-css-variables.ts 里切换dark类并写回--primary;拖取色器,主色 300ms 防抖后全局生效。
🧩 任务四:业务组件里消费变量
【改哪】业务组件自己的<style>,例如src/views/business/overview-card.vue
【改什么】
<style scoped> .business-card { background: hsl(var(--business-primary)); color: hsl(var(--business-foreground)); } </style>【看到什么】组件零 JS、零 watch,明暗切换时颜色自动跟随——这就是"变量先行"的回报。
避坑清单
- 如果你遇到改了变量不生效 → 检查变量名是否被
updateCSSVariables的白名单覆盖:运行时只写回--primary、--success、--warning、--destructive这几个,改--text-color这种已不存在的旧名字当然没反应。 - 如果你遇到暗色下对比度不足 → 检查变量是否只有
:root一份;暗色值必须写在.dark块里,或在BUILT_IN_THEME_PRESETS里补darkPrimaryColor。 - 如果你遇到首屏主题闪烁 → 检查偏好初始化时机:preferences 是 localStorage 持久化的,未读回就渲染会把上一状态闪一下,参考应用启动流程的 preferences 初始化。
- 如果你遇到"Less/SCSS 变量改不动" → 这是编译期变量,产物里已经是死值;想运行时换,一律换成 CSS 变量。
- 如果你遇到自定义颜色后暗色模式"失灵" → 检查是否直接改
<html>的data-theme却跳过了偏好更新,导致colorPrimary与darkPrimaryColor对不上号。
再往前一步
四个任务走下来:预设主色、业务色变量、切换器、组件消费,vue-vben-admin 的换肤闭环就通了。
- 把
BUILT_IN_THEME_PRESETS序列化导入/导出,做主题包分发 - Figma 设计稿 → 色板脚本 → 自动生成
BUILT_IN_THEME_PRESETS条目 - 给每个
data-theme组合加对比度检查,CI 里跑一遍
【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. It's fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考