ref无法自动保持暗黑模式状态,需组合localStorage持久化、系统偏好监听及DOM class切换才能实现刷新不丢、开机即对;useStorage可简化持久化,usePreferredDark配合useStorage可实现用户选择优先、系统偏好兜底的智能逻辑。

直接用 ref 无法自动保持暗黑模式状态——它只是个响应式基础容器,不带持久化或系统偏好感知能力。真正要“保持”,得靠组合逻辑:ref 负责响应式驱动,再配合 localStorage 读写 + 系统偏好监听,才能做到刷新不丢、开机即对。
手动用 ref + localStorage 持久化
这是最轻量、可控性最强的方式,适合不想引入额外依赖的项目:
- 页面加载时,先从
localStorage读取上次保存的值(如'dark'或'light'),作为ref的初始值;没有则 fallback 到系统偏好(window.matchMedia('(prefers-color-scheme: dark)').matches) - 每次切换时,除了更新
ref.value,还要同步写入localStorage - 同时主动给
<html>元素添加/移除darkclass,触发 CSS 变量生效
用 useStorage 替代 ref(推荐)
useStorage 是 VueUse 提供的增强版“带存储的 ref”,一行代码就替代了手动读写 localStorage 的逻辑:
-
const isDark = useStorage('theme-mode', false)—— 自动从 localStorage 读取,初始值为false(浅色),值变更时自动存回 - 它返回的就是一个标准
Ref,可直接用于v-model或条件 class::class="{ dark: isDark }" - 比裸用
ref多了持久化,比useDark更底层、更灵活(比如你想存字符串而非布尔值)
结合 usePreferredDark 实现“自动跟随”逻辑
如果希望默认按系统偏好,但允许用户覆盖,不能只靠 ref 或 useStorage。需要分层判断:
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
立即学习“前端免费学习笔记(深入)”;
- 用
usePreferredDark()获取当前系统倾向(返回Ref<boolean>) - 用
useStorage('theme-mode', null)存用户显式选择(null表示未手动设置) - 定义一个计算属性:
const resolvedMode = computed(() => userChoice.value ?? (preferredDark.value ? 'dark' : 'light')) - 这个
resolvedMode才是真实生效的主题值,它既尊重用户选择,又兜底系统偏好
为什么不用纯 ref?关键缺这三块
纯 ref 不会自动做以下任何事:
- 页面刷新后恢复值(没读 localStorage)
- 监听系统深色偏好变化(没调
matchMedia) - 修改 DOM class 或属性(没触发样式切换)
所以 ref 只是状态载体,真正的“保持”靠的是你补上的那几行读写逻辑和副作用处理。

















