airi 项目中的 useDark 实战:VueUse 响应式深色模式的持久化与主题切换方案
人工智能AI AgentMCP 服务工具调用GUI 自动化语音数字人交互助手【免费下载链接】airi 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器目标是接近 Neuro-sama 的高度支持实时语音聊天、Minecraft 和 Factorio 游玩支持 Web / macOS / Windows。项目地址https://gitcode.com/moeru-ai/airi点击查看免费下载useDark是 VueUse 提供的响应式深色模式组合式函数它把「跟随系统偏好、用户手动切换、localStorage 持久化、DOM 属性联动」这四件事压缩成一个响应式ref。本文以 airi 仓库中的真实接入为线索完整讲解useDark的默认行为、配置项、底层组合原理以及它在 airi 各 Web / 桌面应用中的落地方式读完即可在自己的 Vue 3 项目中直接照搬。useDark 是什么一句话概览官方定义是Reactive dark mode with auto data persistence——一个自带数据持久化的响应式深色模式开关。它的价值在于开发者无需手写matchMedia监听、localStorage读写、classList增删等样板代码只需一行useDark()就能获得一个WritableComputedRefboolean的isDark改它即触发主题切换读它即获得当前主题状态。注意useDark只负责 DOM 属性默认是html上的class的变化不负责实际的样式、主题或 CSS。对应 CSS 选择器如html.dark { ... }仍需自己编写——airi 中正是如此见下文 styles/main.css 的真实做法。基本用法两行代码接入import { useDark, useToggle } from vueuse/core const isDark useDark() const toggleDark useToggle(isDark)isDark是WritableComputedRefbooleantrue表示深色模式写入false即切回浅色。toggleDark是useToggle基于该 ref 生成的切换函数toggleDark()取反toggleDark(true)/toggleDark(false)强制指定值。组件内使用无 setup 逻辑的模板场景template UseDark v-slot{ isDark, toggleDark } button clicktoggleDark() Is Dark: {{ isDark }} /button /UseDark /templateUseDark组件通过作用域插槽暴露isDark与toggleDark适合希望把逻辑完全留在模板中的场景。行为机制三层能力如何组合useDark本质上是useColorMode与usePreferredDark、useStorage协同的产物其完整行为链路如下启动时读取持久化值从localStorage/sessionStoragekey 可配置读取用户是否已经手动设置过配色方案未设置时回退系统偏好若存储中没有用户配置则使用usePreferredDark返回的系统prefers-color-scheme媒体查询结果浅色 / 深色写入时联动 DOM 并持久化当你改变isDarkref 时它会同步更新目标元素的对应属性并把偏好写入存储默认 key 为vueuse-color-scheme实现跨会话记忆。这一组合在参考文档中被明确标注useDark的 related 列表正是useColorMode、usePreferredDark、useStorage三者。理解这一点就能预判它在不同框架下的兼容边界见下文「与 useColorMode 的关系」小节。默认行为Tailwind 风格的 class 切换默认配置采用 Tailwind CSS 官方推荐的深色模式方案——在html标签上应用dark类!--light-- html ... /html !--dark-- html classdark ... /html这是useColorMode默认参数的自然结果目标元素选择器selector默认为html属性attribute默认为class。airi 仓库对这一点有非常直接的印证styles/main.css 中定义了html.dark选择器将背景切换为深色变量并声明color-scheme: dark同时通过html上的transition: all 0.3s ease-in-out让主题切换平滑过渡页面模板中大量使用dark:前缀的 Tailwind / UnoCSS 变体类如 auth/callback.vue 中的dark:bg-orange-950/30这些变体正是依赖html上的dark类才生效。自定义配置适配大多数 CSS 框架若默认的html.dark方案不满足需求可自定义选择器、属性与明暗取值import { useDark } from vueuse/core const isDark useDark({ selector: body, attribute: color-scheme, valueDark: dark, valueLight: light, })其渲染效果如下!--light-- html body color-schemelight ... /body /html !--dark-- html body color-schemedark ... /body /html完整配置项速查UseDarkOptionsUseDarkOptions继承自UseColorModeOptionsBasicColorSchema并剔除了modes与onChanged自身补充以下字段字段说明默认值valueDarkisDarktrue时应用到目标元素的值darkvalueLightisDarkfalse时应用到目标元素的值空串onChanged自定义更新处理器指定后覆盖默认行为签名(isDark, defaultHandler, mode) voidundefined继承自UseColorModeOptions的常用配置同样可用字段说明默认值selector目标元素 CSS 选择器或元素 refhtmlattribute应用到目标元素的 HTML 属性classinitialValue初始配色模式autostorageKey持久化存储的 key传null可关闭持久化vueuse-color-schemestorage存储对象可为localStorage或sessionStoragelocalStoragestorageRef自定义存储 ref提供后跳过useStorage—disableTransition切换时是否禁用过渡避免闪烁trueonChanged完全接管更新逻辑当上述配置仍不满足需求时onChanged提供最大自由度import { useDark } from vueuse/core const isDark useDark({ onChanged(dark) { // update the dom, call the API or something }, })传入后默认的 DOM 更新与持久化行为将被整体覆盖你可以在回调中自由决定如何处理dark值改 DOM、调接口或其他副作用。一个值得注意的配置组合disableTransitionUseColorModeOptions中的disableTransition默认值为true用于在切换主题时通过临时加类禁用 CSS 过渡防止颜色突变时的过渡闪烁这是参考文档引用的 disable-theme-transitions 思路。airi 的实践中两种取值都有出现packages/ui/src/composables/use-theme.ts 全局主题走默认disableTransition: true而 fade-on-hover.vue 中为了按视频教程的明暗素材即时切换显式使用useDark({ disableTransition: false })让页面背景在明暗素材间平滑过渡。airi 仓库实战useTheme 封装与多端复用airi 并未直接在各页面散用useDark而是将其收敛进proj-airi/ui包的一个统一封装 use-theme.tsimport { useDark, useToggle } from vueuse/core import { LocalStorageShim } from ../utils const isDark useDark({ disableTransition: true, // NOTICE: for histoire, used in packages/stage-ui, localStorage global variable exists but storage.getItem is not a function will // thrown, here we added LocalStorageShim to avoid this issue, and it will fallback to real localStorage when its available. storage: localStorage in globalThis localStorage ! null getItem in localStorage typeof localStorage.getItem function ? localStorage : new LocalStorageShim(), }) const toggleDark useToggle(isDark) export function useTheme() { return { isDark, toggleDark, } }这段封装体现了三个实战要点disableTransition: true全局统一采用禁用过渡策略避免切换瞬间的样式闪烁存储环境兼容兜底针对 Histoire 组件文档环境存在localStorage全局变量但getItem不可用做了能力探测回退到LocalStorageShim——这是使用storage选项定制存储源的真实动机模块级单例useDark在模块顶层调用一次所有应用共享同一isDark/toggleDark保证多窗口、多页面主题状态一致。各应用中的调用面Web 端 App.vue 通过useTheme()解构出isDark并在此基础上用computed派生明暗两套主题色#121212深色 /#FFFFFF浅色传给StageTransitionGroup实现转场动画的明暗适配桌面端Electroncontrols-island/index.vue 解构出isDark, toggleDark在舞台控制岛上渲染一个月亮/太阳图标按钮click() toggleDark()一键切换音频波形组件 AudioWaveform.vue 读取isDark决定波形绘制配色其他应用stage-pocket、stage-tamagotchi-kirie 等均通过useTheme()复用同一套主题逻辑。这种「一封装、多端复用」的模式说明useDark的单例特性使其非常适合作为整个应用的主题状态源再通过computed派生需要的派生状态。与 useColorMode 的关系何时升级useDark是useColorMode的布尔特化。useColorMode支持dark/light/ 自定义模式如dim、cafe以及auto模式并额外暴露system系统偏好、store用户覆盖值、state合成结果三个衍生 refconst { system, store } useColorMode() system.value // dark | light store.value // dark | light | auto const myColorMode computed(() store.value auto ? system.value : store.value)决策建议只要二元明暗切换用useDark最简洁需要三态以上含跟随系统或自定义主题名时升级为useColorMode若需要精细控制useColorMode还提供attribute: theme、自定义modes映射等配置可直接从 useColorMode.md 参考文档获取完整类型声明。常见坑位与规避模板中直接绑定 toggle 函数clicktoggleDark会把事件对象作为参数传入导致行为异常务必写作clicktoggleDark()该警示同样见于 useToggle.md 的 Caution 一节持久化 key 冲突默认vueuse-color-scheme为全站共享多实例使用不同语义时需显式指定storageKey存储对象不可用某些测试 / 文档环境存在残缺的localStorage应如 airi 那样做能力探测并准备 shim 兜底SSR / 无 window 环境useDark依赖浏览器 API服务端渲染时需在客户端挂载后再调用可在onMounted或tryOnMounted中执行。小结useDark把「系统偏好监听 手动覆盖 本地持久化 DOM 联动」整合为一个响应式布尔 ref是 Vue 3 项目接入深色模式的最短路径。airi 的实践进一步展示通过useTheme()封装成单例后Web、PWA、Electron 等多端共享同一主题源再用computed派生主题色与转场配色构成了一套完整、可复用的主题体系。相关完整类型声明与配置项可直接参考仓库中的 useDark.md 原始文档。赞分享人工智能AI AgentMCP 服务工具调用GUI 自动化语音数字人交互助手【免费下载链接】airi 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器目标是接近 Neuro-sama 的高度支持实时语音聊天、Minecraft 和 Factorio 游玩支持 Web / macOS / Windows。项目地址https://gitcode.com/moeru-ai/airi点击查看免费下载相关推荐airi 项目中的 useDark 实战指南基于 VueUse 实现带自动持久化的响应式暗色模式airi 项目中的 useDark 实战指南基于 VueUse 实现带自动持久化的响应式暗色模式 导读 useDark 是 VueUse 提供的一个 Brow人工智能AI 应用大模型AI Agent交互助手语音数字人后端前端桌面应用移动开发GUI 自动化MCP 服务VueUse useDark 深度实战响应式暗色模式与自动持久化的完整实现指南VueUse useDark 深度实战响应式暗色模式与自动持久化的完整实现指南 在 Vue 3 应用中接入暗色模式Dark Mode时 useDark前端VueUse useDark 实战指南在 Vue 3 中实现响应式暗色模式与自动持久化VueUse useDark 实战指南在 Vue 3 中实现响应式暗色模式与自动持久化 useDark 是 VueUse 在 Vue 3 中提供的响应式暗色模前端上一篇群里谁发言最多用wechat-cli一键生成微信聊天统计与24小时活跃图的完全指南下一篇用Talivia追踪订阅生命周期退款、争议与流失预警如何帮你减少SaaS流失率创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考