必须同时配置 manifest.json、theme.json 和运行时主题同步,三者缺一不可;否则页面跳转或冷启动时必然闪白/闪黑。
必须同时配置 manifest.json、theme.json 和运行时主题状态同步,三者缺一不可;否则页面跳转或冷启动时必然闪白/闪黑。
manifest.json 和 theme.json 怎么配才生效
uni-app 的暗黑模式不是靠 CSS 媒体查询自动触发的,而是平台层读取配置后注入变量。配置错一个地方,整个链路就断了。
-
manifest.json中每个目标平台节点(如app-plus、mp-weixin、h5)都必须显式写"darkmode": true和"themeLocation": "theme.json",不能只配一个平台 -
theme.json必须放在项目根目录,结构严格为{"light": {}, "dark": {}},键名大小写敏感,不能写成Light或night -
pages.json里能用@xxx引用的字段极少:仅navigationBarBackgroundColor、navigationBarTextStyle、backgroundColor、tabBar.color等几个,且小程序中tabBar.borderStyle只认"black"/"white"字符串
App.vue 里怎么同步主题并避免闪屏
App 端不透出系统主题变更事件,也不能靠 prefers-color-scheme 自动响应——iOS/Android 原生容器在 HBuilderX 4.76+ 才支持 uni.onThemeChange,而且必须先开 darkmode: true 才注册成功。
- 用户点击切换按钮时,立刻执行
uni.setStorageSync('theme', 'dark')或'light',key 名要固定,值必须是字符串 -
App.vue的onLaunch和onShow都要读取uni.getStorageSync('theme'),fallback 到uni.getSystemInfoSync().theme(部分平台返回"light"/"dark") - 用
:class="themeClass"绑定根<view></view>,不要改document.body.className(小程序无效),也不要只设data-theme属性(nvue 和部分平台不识别) - 推荐 class 命名如
theme-light/theme-dark,所有样式都基于该 class 做嵌套定义,比如.theme-dark .btn,别依赖纯:root变量更新
为什么 pages.json 里的 @变量没变色
这是最常被忽略的硬性依赖:@ 变量生效的前提是 theme.json 被正确加载,而加载失败时控制台完全静默,没有任何报错提示。
- 检查
themeLocation路径是否写错(比如写成"./theme.json"或"static/theme.json"),HBuilderX 4.83+ 会直接忽略错误路径 - 确认
theme.json文件编码是 UTF-8 无 BOM,文件内容 JSON 格式合法,且只有light和dark两级对象 - @ 变量只在编译期注入到原生层,运行时改本地存储不会触发导航栏重绘——所以手动切换后,必须调用
uni.reLaunch或uni.$emit通知页面刷新,否则pages.json定义的导航栏颜色永远卡在旧值
真正难的不是写几行 CSS 变量,而是让三端(App、小程序、H5)在冷启动、热切后台、系统主题变更、用户手动切换这四种场景下,都保持一致且无闪烁。任何一环漏掉——比如忘了在 onShow 里再读一次主题,或者 theme.json 多了个空格——都会在某个平台某个时机暴露出来。


















