应使用 uni.setStorageSync 在用户点击切换按钮时立即存储主题值(如 'light'/'dark'),并在 App.vue 的 onLaunch 和 onShow 中读取并动态绑定根节点 class 实现样式切换,避免闪屏与平台兼容问题。

uni-app 里怎么用 uni.setStorageSync 存主题配置
主题切换的前提是用户选择能被记住,否则每次重启都是默认色。最稳妥的方式是用 uni.setStorageSync 把当前主题(比如 'dark' 或 'light')存到本地,而不是依赖内存变量或 vuex 临时状态。
注意:不能只在页面里存,得在用户点击切换按钮的那一刻就写入;也不能等 App.vue 的 onLaunch 再读——因为页面可能先于 App.vue 渲染,导致闪屏(白/黑屏跳变)。
- 存的时候用固定 key,比如
'theme_mode',避免拼错或大小写不一致 - 值建议限定为字符串
'light'/'dark'/'auto',别用布尔值,否则 H5 和小程序平台行为不一致 - App.vue 的
onLaunch和onShow都要读一次uni.getStorageSync('theme_mode'),覆盖初始 class
如何让 CSS 真正响应主题变化而不重载页面
uni-app 没有原生 CSS 自定义属性(CSS Custom Properties)的跨平台 runtime 支持,尤其在微信小程序里,:root 变量无法动态更新。所以不能只靠 document.documentElement.setAttribute('data-theme', 'dark') + CSS 变量完事。
真实可行的是:用 class 控制整页样式,并通过 uni.addStyle 或 class 切换触发重绘。但要注意,直接改 document.body.className 在小程序里无效,必须作用在根 view 上。
- 在 App.vue 的
根节点加动态 class: -
themeClass是计算属性,返回'theme-light'/'theme-dark',由 store 或全局变量驱动 - 所有主题相关样式都写成
.theme-dark .header、.theme-light .button这种嵌套形式,不要依赖 CSS 变量做核心切换 - H5 端可额外用
document.documentElement.setAttribute('data-theme', theme)做兼容,但别把它当主力
为什么 prefers-color-scheme 在小程序里根本不起作用
这是个常见误解:以为监听 window.matchMedia('(prefers-color-scheme: dark)') 就能自动适配微信/支付宝小程序。实际上,小程序 WebView 不暴露系统级媒体查询能力,matchMedia 在多数小程序基础库中返回空对象或直接报错。
真正能用的“自动”逻辑,只能靠客户端能力兜底:App 端可用 native API 获取系统主题(如 uni.getSystemInfoSync().platform === 'ios' && iOS 13+ 才有),但微信小程序连这个都不提供。所以「自动」本质是伪需求,必须降级为「上次用户选择 + 手动开关」。
- 别在
onLoad里调matchMedia,H5 可以,小程序会静默失败 - 如果真要做「首次进入按系统」,只在 H5 端判断,其他平台一律 fallback 到
light - uni-app 的
uni.getSystemInfo返回的theme字段仅在部分 Android 客户端有效,且不可靠,别依赖
暗黑模式下图片和 icon 怎么避免发灰或看不见
不是所有图片都适合“一图通用”。纯白图标在暗色背景上消失、浅色插画在深色下对比度崩坏,是上线后最常被 QA 打回来的问题。
解决方案不是 JS 控制 src,而是用 CSS picture + media 或平台条件编译。但 uni-app 的 不支持 srcset,所以得换思路。
- 把关键 icon 拆成两套:命名带
-light/-dark后缀,例如icon-home-dark.png - 用 computed 动态拼接路径:
require(`@/static/icons/${iconName}-${theme}.png`),注意 webpack 别 alias 错 - 渐变色背景、阴影类样式必须单独写暗色版,比如
box-shadow: 0 2px 12px rgba(0,0,0,0.1)在暗色下要改成rgba(255,255,255,0.08) - 慎用
filter: brightness()或invert(),会导致文字反色、图标失真,仅作临时 hack
最麻烦的其实是第三方组件库(如 uView、uCharts),它们的主题机制往往只适配 Vue 版本,uni-app 小程序编译后 class 名被 hash,手动覆盖成本极高。遇到这种,优先查它是否提供 theme prop,没有就 fork 后改源码——别硬套 CSS 变量。










