主题持久化三步:存字符串(如"dark")、页面就绪后读取并设为data-theme、切换时同步dom与localstorage;配合[data-theme]css变量实现无闪屏、跨标签页响应。

用 localStorage 存一个字符串(比如 "dark" 或 "light"),页面加载时立刻读取并设到 HTML 根节点上,切换时同步更新 DOM 和存储——三步就能让主题在刷新、关闭再打开后依然保持。
存主题:只存简单字符串,别存对象
用户点按钮切换主题时,直接写入字符串值:
- 用
localStorage.setItem('theme', 'dark')保存暗色模式 - 用
localStorage.setItem('theme', 'light')保存亮色模式 - 不推荐存对象或布尔值,比如
{ mode: 'dark' },得 JSON 序列化又反序列化,没必要 - 小写统一命名,避免后续判断时因大小写出错
读主题:DOM 就绪后立即执行,防闪屏
必须等页面结构准备就绪再读取和应用,否则会先显示默认样式、再跳变成目标主题(FOUC):
- 监听
DOMContentLoaded,或检查document.readyState === 'complete' - 读取:
const savedTheme = localStorage.getItem('theme') - 若返回
null或空字符串,可 fallback 到系统偏好:window.matchMedia('(prefers-color-scheme: dark)').matches - 设到根节点:
document.documentElement.dataset.theme = savedTheme || 'light'
同步更新:按钮点击 + 跨标签页响应
不只是当前页改样式,还要确保所有相关场景都一致:
- 点击按钮后,先更新 DOM(如
dataset.theme),再调用setItem写入存储 - 加一层判断,只在主题实际变化时才写入,避免无效操作
- 监听
storage事件,响应其他同源标签页的主题变更:window.addEventListener('storage', e => { if (e.key === 'theme') document.documentElement.dataset.theme = e.newValue }) - 注意:该事件不会在触发修改的当前窗口触发,只通知其他窗口
配合 CSS:用 data-theme 属性驱动样式
HTML 结构和 CSS 要配合好,才能让 JS 控制简洁高效:
- CSS 中用
:root定义默认变量,[data-theme="dark"]下重写变量值 - 例如:
[data-theme="dark"] { --bg: #121212; --text: #e0e0e0; } - 所有元素用
background: var(--bg)、color: var(--text)引用,无需反复切 class - 比给 body 加
class="dark"更语义化,也更利于状态管理
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











