uni-app深色模式需theme.json与manifest.json严格对齐:manifest.json各平台节点须显式配置"darkmode":true和"themeLocation":"theme.json",theme.json须置于根目录且变量名仅限light/dark,pages.json仅支持特定全局样式字段引用@变量,组件内联样式不生效,需用CSS变量或class切换,微信小程序tabBar.borderStyle仅支持black/white字符串,手动切换主题需强制重绘页面,鸿蒙和安卓nvue有特殊适配要求。

theme.json 配置必须和 manifest.json 对齐,否则深色模式不生效
uni-app 的深色模式不是靠 CSS 媒体查询自动触发的,而是依赖平台层识别 theme.json 并注入对应变量——如果配置没对上,iOS、鸿蒙、H5 甚至微信小程序都会静默失败,界面毫无变化。
-
manifest.json中必须在各平台节点(如app-plus、app-harmony、mp-weixin)显式写入"darkmode": true和"themeLocation": "theme.json",不能只写一个平台 -
theme.json必须放在项目根目录,路径大小写敏感;若放错位置(比如在static/下),HBuilder X 4.83+ 会直接忽略,控制台也不报错 - 变量名只能是
light和dark两级,不能自定义成night或midnight,否则 pages.json 里@navBgColor这类引用会 fallback 到空值
pages.json 中的颜色变量仅限全局样式字段,不能用于组件内联样式
很多人以为写了 @bgColor 就能在所有地方用,结果在 里失效——这是设计限制,不是 bug。
- 支持
@xxx的字段只有:navigationBarBackgroundColor、navigationBarTextStyle、backgroundColor、tabBar下的color/selectedColor/backgroundColor/borderStyle - 组件内部颜色必须用 CSS 变量方案(
:root+[data-theme="dark"])或 class 切换,不能依赖theme.json注入 - 微信小程序中
tabBar.borderStyle只接受"black"或"white"字符串,哪怕theme.json里写成"#ffffff"也会被截断为"white"
手动切换主题时,必须主动触发页面重绘,否则样式卡在旧状态
用 switch 控件调用 uni.setStorageSync('theme', 'dark') 很容易,但如果不通知当前页面更新,pages.json 里定义的导航栏颜色根本不会变——因为 pages.json 是编译期注入,运行时改本地存储不影响已渲染的 DOM。
- 推荐做法:在 App.vue 的
onLaunch和onShow中读取主题,然后调用uni.reLaunch({ url: '/pages/index/index' })强制刷新(轻量页可用uni.$emit+watch监听) - 监听系统变化要用
uni.matchMedia('(prefers-color-scheme: dark)'),不是window.matchMedia,后者在 App 端不可靠 - 安卓端 nvue 页面不支持
data-theme类名切换,得用style绑定或v-if/v-else分开写两套结构
uni-ui 组件默认不响应深色模式,必须逐个打补丁
像 uni-number-box、uni-datetime-picker 这类组件大量使用内联样式,@media (prefers-color-scheme: dark) 在它们内部基本无效,得手动覆盖。
- 最稳妥方式:在
uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue的块末尾加@media (prefers-color-scheme: dark) { ... },并给关键属性加!important - 不要只改
App.vue全局样式,因为 uni-ui 组件的 scoped style 会隔离掉外部规则 - 图标类组件(如 tabbar icon)必须准备两套图:浅色用
icon.png,深色用icon-dark.png,并在pages.json中根据主题动态指定iconPath和selectedIconPath
实际项目里最容易漏的是鸿蒙平台的 safearea.bottom.offset 配置和安卓 nvue 的 class 切换逻辑——这两处不处理,tabbar 会在深色模式下错位或文字看不见,而且问题只出现在真机,模拟器完全不复现。











