uni-app x 暗黑主题适配完全指南:osTheme / hostTheme / appTheme 三套主题体系与媒体查询实战
2026/9/20 10:27:30 网站建设 项目流程
  • 示例工程
  • 前端
  • 移动开发
  • 跨平台

【免费下载链接】uni-app

A cross-platform framework using Vue.js

项目地址:https://gitcode.com/gh_mirrors/un/uni-app
点击查看免费下载

本文以 uni-app x 官方主题适配文档为骨架,系统讲解light/dark暗黑模式适配的完整链路:从osThemehostThemeappTheme三种主题概念的差异,到manifest.jsontheme.jsonpages.json的配置方式,再到「媒体查询」与「监听主题动态切换 class」两套适配方案,最后逐项拆解uni.setAppThemeuni.onAppThemeChange等主题 API 的参数与行为。读完本文,你可以为自己的 uni-app x 项目落地「跟随系统」或「App 内独立切换」的暗黑主题能力,并理解底层 API 的触发时机与平台兼容差异。

主题体系基础概念:light 与 dark

iOS 13+Android 10+系统级提供了暗黑模式/深色模式,系统之前的模式称为light(亮色),暗黑模式称为dark(深色)。低于上述版本的手机,系统层没有暗黑模式的概念,无法通过 API 获取或监听 OS 主题。

在 uni-app x 中,主题不是一个单一概念,而是分为3 种主题OSThemehostThemeappTheme。每种主题在不同平台的支持度不同,获取、设置和监听变化的方式也不同,其全貌如下表所示:

| 主题概念 | 描述 | App | Web | 小程序 | 获取方式 | 设置方式 | 监听变化 | | -- | -- | -- | -- | -- | -- | -- | -- | | osTheme | 手机 OS 的当前主题 | √ | x | x | uni.getDeviceInfo | - | uni.onOsThemeChange | | hostTheme | 浏览器或小程序宿主的当前主题 | x | √ | √ | uni.getAppBaseInfo | - | uni.onHostThemeChange | | appTheme | App 当前主题 | √ | X | x | uni.getAppBaseInfo | uni.setAppTheme | uni.onAppThemeChange |

注:获取主题除了上表列出的 API 外,也可以使用 uni.getSystemInfo(返回osThemehostThemeappTheme属性),uni.getDeviceInfo 与 uni.getAppBaseInfo 是更聚焦的取值入口。

Web 和小程序平台的注意点

  • Web 和小程序没有能力获取 OS 的主题,只能获取浏览器或小程序宿主的主题,即hostTheme
  • 可以选择不响应hostTheme(darkmode设置为false),也可以根据 hostTheme调整自身的表现darkmode设置为true)。
  • 一旦在 manifest 里开启darkmode,pages.json 的 tabbar、导航栏、页面背景色,以及某些浏览器或小程序自带的组件和涉及 UI 的 API,都会跟随 hostTheme 变化,开发者的应用无法控制这些 UI 的主题。例如浏览器的alert()、小程序的showModal

appTheme 概念的用途

独立设置主题的场景常见于 App 平台,因此 App 平台新增了appTheme概念。appTheme 有几个用途:

  1. 独立于 osTheme 设置主题:App 可以有自己的主题,不强制跟随系统;
  2. 方便开发者和插件作者协作:推荐各个插件作者在涉及 UI 时支持主题适配,响应 App 的主题变化;
  3. uni-app x 框架自带的一些 UI 页面会响应 appTheme 变化,例如showActionSheet、pages.json 的页面设置等。

先明确需求:三种适配做法

开发者做主题适配时,需要先明确自己的需求,以下 3 种做法需要做的事情完全不一样:

1. 只做 dark,不做 light

  • 只需要在 pages.json 的globalStyle写死页面背景、tabBar 以及 navigationBar 的背景前景颜色;
  • 在 uvue 页面里写死暗色系颜色值,无需动态判断、无需 css 变量;
  • 如果属于这种需求,本文接下来的内容都不用再看。

2. 只跟随「上家」(App 的上家是 osTheme,小程序和 web 的上家是 hostTheme),不需要给用户提供手动切换

  • 需要做下面讲到的配置与监听,见后文。

3. App 上提供独立的 light/dark/auto 选项给用户,可以根据 osTheme,也可以独立设置

  • 需要做更多事情,了解 appTheme 相关 API,见后文。

主题适配处理内容范围

开发者做主题适配时需处理的内容范围,涉及manifest.jsontheme.jsonpages.jsonapp.uvue,以及自己的 uvue 页面。下面依次说明。

1. manifest.json:开启 darkmode

Web 端、小程序需要配置 manifest.json 中webmp-weixin根节点的"darkmode": true。配置后如果不生效请重新编译运行

{ "mp-weixin": { "darkmode": true }, "web": { "darkmode": true } }

本仓库的示例工程 src/manifest.json 正是这样配置的:mp-weixin节点下设置了"darkmode": trueweb节点下同样设置了"darkmode": true,同时还开启了"uni-app-x": { "vapor": true, "styleIsolationVersion": "2" }(Vapor 蒸汽模式),这与下文「媒体查询适配」方案在新版 App 平台的能力直接相关。

2. pages.json 和 theme.json:全局样式的亮暗切换

pages.json 的亮黑设置,需要通过 theme.json 处理。

要特别注意:适配暗黑模式时,如果要适配 pages.json 中的 tabbar 和 NavigationBar,必须放置 theme.json 文件

下面是 pages.json 中的globalStyle设置,在属性值中通过@来引用 theme.json 中定义的值:

"globalStyle": { "navigationBarTextStyle": "@navigationBarTextStyle", "navigationBarBackgroundColor": "@navigationBarBackgroundColor", "backgroundColor": "@backgroundColor", "backgroundTextStyle": "@backgroundTextStyle" },

下面是 theme.json 的样例。theme.json 的位置放在pages.json 同级目录下(即项目根目录)。

lightdark节点下,分别命名一批同名的变量,并分别赋值。这些变量可以在 pages.json 里直接引用:

{ "light": { "navigationBarTextStyle": "white", "navigationBarBackgroundColor": "#007AFF", "backgroundColor": "#efeff4", "tabBarPagebackgroundColorContent": "#efeff4", "backgroundTextStyle": "dark" }, "dark": { "navigationBarTextStyle": "white", "navigationBarBackgroundColor": "#1F1F1F", "backgroundColor": "#1F1F1F", "tabBarPagebackgroundColorContent": "#1F1F1F", "backgroundTextStyle": "light" } }

完整的 theme.json 教程详见 theme.json。

几个关键约束:

  • theme.json 里的变量仅能用于 pages.json,uvue 页面不能引用
  • 在 web 和小程序中,theme.json 的 dark 部分生效的前提是:
    1. manifest 设置了darkmode: true
    2. 浏览器和小程序宿主(如微信)的主题外观是 dark;
  • 在 App 中,可以通过 manifest.json 的app.defaultAppTheme配置应用默认主题,可取值为lightdarkauto默认值为light。配置为auto时,appTheme 会跟随 OS 主题变化:
{ "app": { "defaultAppTheme": "auto" } }

如果应用为用户提供主题切换功能,可以在运行时通过 uni.setAppTheme 设置lightdarkauto

theme.json 为什么能避免「转场闪白 / 闪黑」:按照 themejson.md 的说明,在页面onLoad中设置页面样式会来不及——某些平台页面早于 onLoad 就可以创建并开始窗体转场动画,会导致动画刚开始的背景色、navigationBar 背景色与 onLoad 后不一致。theme.json 让新页面创建时第一时间就根据 pages.json 的设置初始化,从而避免闪白闪黑。

theme.json 变量支持的属性范围(来自 themejson.md):

  • 全局配置globalStyle与页面style支持:navigationBarBackgroundColornavigationBarTextStylebackgroundColorbackgroundTextStyle
  • 全局配置tabbar支持:colorselectedColorbackgroundColorborderStylelist(含iconPathselectedIconPath)。

本仓库的示例工程 src/theme.json 就是一个完整的实战样例:在light节点下定义了navigationBarTextStyle: "white"navigationBarBackgroundColor: "#007AFF"backgroundColorContent: "#efeff4"tabBarColor: "#7A7E83"tabBarSelectedColor: "#007AFF"tabBarBackgroundColor: "#F8F8F8"等变量;在dark节点下分别对应"#1F1F1F""#646464""#cacaca""#F8F8F8"等暗色取值,连 tabBar 的图标路径(tabBarComponentIconPathtabBarAPIIconPath等)都做了亮暗双份定义。

完成上述基础配置后,页面和组件的主题样式可以根据平台及版本选择以下两种方案之一。

3. 使用媒体查询适配主题(推荐)

以下平台可以使用@media (prefers-color-scheme: light)@media (prefers-color-scheme: dark)设置主题样式:

  • Web 和小程序平台
  • HBuilderX 5.25+ 的 App 平台蒸汽模式(Vapor 模式)

在支持上述能力的平台,推荐优先使用媒体查询适配主题

媒体查询会根据hostThemeappTheme自动匹配。主题变化时,匹配的样式也会自动更新,无需监听主题变化、维护响应式变量或动态切换 class。详见 @media 媒体查询。

页面只需要使用固定的 class,通过媒体查询分别定义亮色和暗色样式:

<template> <view class="page"> <text class="title">根据当前主题显示不同颜色的文字</text> </view> </template> <style> @media (prefers-color-scheme: light) { .page { --text-color: #333333; } } @media (prefers-color-scheme: dark) { .page { --text-color: #ffffff; } } .title { color: var(--text-color); } </style>

媒体查询和 page 选择器,可以在app.uvue里使用,从而实现所有页面的效果批量控制。除非页面配置了禁止全局样式影响(样式隔离)。

如果 App 平台需要为用户提供lightdarkauto选项,直接调用uni.setAppTheme即可。appTheme 变化后,媒体查询会自动更新匹配的样式。

仓库佐证:本仓库的示例工程在 src/common/uni.css 以及多个页面(如 src/pages/tabBar/API.uvue、src/pages/component/text/text-props.uvue 等)中广泛使用@media (prefers-color-scheme: light/dark)定义亮暗样式,配合 src/App.uvue 在onLaunch中调用checkSystemTheme()完成主题初始化,是媒体查询方案在真实工程中的落地范本。

4. 监听主题并动态切换 class(老版兼容方案)

以下 App 平台场景,由于不支持媒体查询,只能通过 API 监听主题变化,然后动态切换 class

  • HBuilderX 5.25 之前的 App 平台
  • App 平台 VDOM 模式

在已支持媒体查询的平台,如果业务逻辑还需要读取当前主题状态,可以另外使用主题 API 获取和监听,但样式仍可使用媒体查询,无需动态切换 class

为了在同一套代码中兼容上述 App 平台场景,以下示例在各端统一使用动态 class。为避免每个页面都监听主题变化,可以在app.uvue中获取并监听主题,将结果存放在store/index.uts中,供各页面使用。

场景一:只跟随「上家」,不独立设置主题

如果应用只需要跟随上家,App 平台需要先将app.defaultAppTheme配置为auto,然后可以这样处理:

// app.uvue import { state } from '@/store/index.uts' onLaunch(() => { // #ifdef WEB || MP-WEIXIN state.isDark = (uni.getAppBaseInfo().hostTheme == 'dark') uni.onHostThemeChange((result) => { state.isDark = (result.hostTheme == 'dark') }) // #endif // #ifdef APP state.isDark = (uni.getDeviceInfo().osTheme == 'dark') uni.onOsThemeChange((result: OsThemeChangeResult) => { state.isDark = (result.osTheme == 'dark') }) // #endif })

store/index.uts的内容如下:

type State = { // 是否为暗黑主题 isDark: boolean } export const state = reactive({ isDark: false } as State)

场景二:App 允许用户独立设置主题

如果 App 平台允许用户独立设置主题,则需要获取和监听appTheme

// app.uvue import { state } from '@/store/index.uts' onLaunch(() => { // #ifdef WEB || MP-WEIXIN state.isDark = (uni.getAppBaseInfo().hostTheme == 'dark') uni.onHostThemeChange((result) => { state.isDark = (result.hostTheme == 'dark') }) // #endif // #ifdef APP const appTheme = uni.getAppBaseInfo().appTheme state.isDark = appTheme == 'auto' ? uni.getDeviceInfo().osTheme == 'dark' : appTheme == 'dark' uni.onAppThemeChange((result: AppThemeChangeResult) => { state.isDark = (result.appTheme == 'dark') }) // #endif })

注意:当appThemeauto时,需要结合 osTheme 判断真实主题;当 appTheme 从auto切到具体值或跟随 OS 变化时,onAppThemeChange会在真实主题变化时触发(详见下文 API 版本历史说明)。

可以在app.uvue的全局样式中定义亮色和暗色 class。除非页面或组件的样式隔离策略禁止全局样式影响,否则页面可以直接使用这些 class:

.theme-light { --text-color: #333333; } .theme-dark { --text-color: #ffffff; }

页面根节点根据state.isDark动态切换 class:

<template> <view :class="state.isDark ? 'theme-dark' : 'theme-light'"> <text class="title">根据当前主题显示不同颜色的文字</text> </view> </template> <script setup lang="uts"> import { state } from '@/store/index.uts' </script> <style> .title { color: var(--text-color); } </style>

性能与体验提醒:动态切换 class 由于要执行 script,性能没有媒体查询高。另外动态切换 class 的代码与 theme.json 的执行可能不在同一帧,会造成 theme.json 先生效、class 后生效,有闪烁感。推荐升级到 HBuilderX 5.25 的蒸汽模式,使用媒体查询方案适配主题。

仓库佐证:本仓库 src/store/index.uts 中定义了全局响应式状态state.isDarkMode,并封装了checkSystemTheme()函数:Web / 微信小程序端通过uni.getAppBaseInfo().hostTheme初始化并uni.onHostThemeChange监听宿主主题;App 端通过uni.getSystemInfo结合appThemeosTheme判断真实主题,并用uni.onAppThemeChange持续监听(见 src/store/index.uts)。而 src/App.uvue 在onLaunch里调用checkSystemTheme(),正是把「主题监听集中在应用入口、全局状态供所有页面共享」这一模式的真实实现。

内置组件和 UI 相关 API 的适配说明

uni-app x 的App 和 Web 平台框架中自带的界面,均已适配暗黑模式(小程序平台由小程序宿主自行适配),目前包括:

  • uni.showActionSheet(HBuilderX 4.51+)
  • uni.showModal(HBuilderX 4.61+)
  • uni.chooseLocation(HBuilderX 4.33+)
  • uni.openLocation(HBuilderX 4.41+)
  • uni.chooseImage/chooseVideo/chooseMedia/chooseFile:当调用系统的选择界面时,该界面的主题跟随osTheme,应用层无法干预

另外,uni-app x 的内置组件在 App 和 Web 平台均支持 css 设置所有样式,这样就可以在所有样式控制中使用 css 变量;但小程序平台的内置组件依赖其自身实现,有的组件需要通过属性控制样式,此时无法使用 css 变量。

主题 API 详解

以下 API 的源码实现位于独立的 uni-theme 模块(uni_modules/uni-theme),行为说明以本文为准。

uni.setAppTheme(options)

设置应用主题

uni.setAppTheme用于设置 App 当前主题。开发者仍需为不同主题定义相应的页面和组件样式。它的作用是:

  1. 根据 theme.json,设置 pages.json 的亮/暗主题;
  2. HBuilderX 5.25+,在 App 平台蒸汽模式下,自动更新@media (prefers-color-scheme: light)@media (prefers-color-scheme: dark)匹配的样式;
  3. 触发uni.onAppThemeChange,开发者和组件作者均可监听这个事件,自行响应将页面设置为对应的亮/暗风格。

当然组件作者也可以不监听onAppThemeChange,而是暴露主题切换 API 给开发者,由开发者监听主题切换,再调用组件的主题切换 API。

uni-app x 的 UI 相关 API(比如showModal),也会响应setAppTheme

兼容性

| Web | 微信小程序 | Android | iOS | HarmonyOS | | :- | :- | :- | :- | :- | | x | x | 4.18 | 4.18 | 4.71 |

参数

| 名称 | 类型 | 必填 | 兼容性 | | :- | :- | :- | :-: | | options |SetAppThemeOptions| 是 | Web: x; 微信小程序: x; Android: 4.18; iOS: 4.18; HarmonyOS: 4.71 |

options 的属性描述

| 名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 | | :- | :- | :- | :- | :-: | :- | | theme | string | 是 | | Web: x; 微信小程序: x; Android: 4.18; iOS: 4.18; HarmonyOS: 4.71 | 主题 | | success | (result: SetAppThemeSuccessResult) => void | 否 | null | Web: x; 微信小程序: x; Android: 4.18; iOS: 4.18; HarmonyOS: 4.71 | 接口调用成功的回调函数 | | fail | (result: AppThemeFail) => void | 否 | null | Web: x; 微信小程序: x; Android: 4.18; iOS: 4.18; HarmonyOS: 4.71 | 接口调用失败的回调函数 | | complete | (result: any) => void | 否 | null | Web: x; 微信小程序: x; Android: 4.18; iOS: 4.18; HarmonyOS: 4.71 | 接口调用结束的回调函数(调用成功、失败都会执行) |

theme 的属性描述

| 合法值 | 兼容性 | 描述 | | :- | :-: | :- | | light | Web: x; 微信小程序: x | 亮色模式 | | dark | Web: x; 微信小程序: x | 深色模式 | | auto | Web: x; 微信小程序: x | 跟随系统模式 |

SetAppThemeSuccessResult 的属性值

| 名称 | 类型 | 必备 | 兼容性 | | :- | :- | :- | :-: | | theme | string | 是 | Web: x; 微信小程序: x |

AppThemeFail 的属性值

| 名称 | 类型 | 必备 | 兼容性 | 描述 | | :- | :- | :- | :-: | :- | | errCode | number | 是 | Web: x; 微信小程序: x; Android: 4.18; iOS: 4.18; HarmonyOS: 4.71 | 错误码(702001 参数错误;2002000 未知错误) | | errSubject | string | 是 | Web: x; 微信小程序: x | 统一错误主题(模块)名称 | | data | any | 否 | Web: x; 微信小程序: x | 错误信息中包含的数据 | | cause | Error | 否 | | 源错误信息,可以包含多个错误,详见 SourceError | | errMsg | string | 是 | Web: x; 微信小程序: x | |

errCode 合法值702001(参数错误)、2002000(未知错误)。

示例

uni.setAppTheme({ theme: "auto", success: function() { console.log("设置appTheme为 auto 成功") }, fail: function(e: IAppThemeFail) { console.log("设置appTheme为 auto 失败,原因:", e.errMsg) } })

uni.onAppThemeChange / uni.offAppThemeChange

开启 / 取消监听应用主题变化

版本历史调整(重要,涉及回调语义):

  • HBuilderX 4.18 版本:uni.setAppTheme设置的 theme 值变化时触发本监听回调,回调参数中的appTheme值可能是"light" | "dark" | "auto"。在 app 平台设置应用的 theme 值为auto后,需再次查询 osTheme 来判断当前的真实主题;如果应用主题是auto,那么需要同时监听 osTheme 的变化。
  • HBuilderX 4.19 版本起:应用的light/dark 主题真正发生变化时才触发监听回调。无论是手动设置 setAppTheme 还是跟随 osTheme 变化,只要真正变化了就会触发本监听。回调参数中的appTheme值只能是"light" | "dark"

onAppThemeChange 兼容性

| Web | 微信小程序 | Android | iOS | HarmonyOS | | :- | :- | :- | :- | :- | | x | x | 4.18 | 4.18 | 4.71 |

参数callback: (res: AppThemeChangeResult) => void,必填。

AppThemeChangeResult 的属性值

| 名称 | 类型 | 必备 | 兼容性 | 描述 | | :- | :- | :- | :-: | :- | | appTheme | string | 是 | Web: x; 微信小程序: x; Android: 4.18; iOS: 4.18; HarmonyOS: 4.71 | 应用主题 |

appTheme 合法值light(亮色模式)、dark(深色模式)。

返回值number(callbackId,用于注销监听)。

示例

//callbackId 用于注销监听 val callbackId = uni.onAppThemeChange((res: AppThemeChangeResult) => { console.log("onAppThemeChange", res.appTheme) })
val callbackId = uni.onAppThemeChange((res: AppThemeChangeResult) => { console.log("onAppThemeChange", res.appTheme) }) //... //... //注销监听 uni.offAppThemeChange(this.appThemeChangeId)

offAppThemeChange兼容性:Web: x、Android: 4.18、iOS: 4.18、HarmonyOS: 4.71;参数id: number必填。

uni.onOsThemeChange / uni.offOsThemeChange

开启 / 取消监听系统主题变化

onOsThemeChange 兼容性

| Web | 微信小程序 | Android | iOS | HarmonyOS | | :- | :- | :- | :- | :- | | x | x | 4.18 | 4.18 | 4.71 |

参数callback: (res: OsThemeChangeResult) => void,必填。

OsThemeChangeResult 的属性值

| 名称 | 类型 | 必备 | 兼容性 | 描述 | | :- | :- | :- | :-: | :- | | osTheme | string | 是 | Web: x; 微信小程序: x; Android: 4.18; iOS: 4.18; HarmonyOS: 4.71 | 系统主题 |

osTheme 合法值light(亮色模式)、dark(深色模式)。

返回值number(callbackId,用于注销监听)。

示例

//callbackId 用于注销监听 val callbackId = uni.onOsThemeChange((res: OsThemeChangeResult)=> { console.log("onOsThemeChange---", res.osTheme) })
val callbackId = uni.onOsThemeChange((res: OsThemeChangeResult)=> { console.log("onOsThemeChange---", res.osTheme) }) ... ... //注销监听 uni.offOsThemeChange(callbackId)

特别注意

  • Android 10、iOS 13 才开始支持深色模式主题dark更低版本无法获取、监听 OS 的主题
  • iOS 平台应用在进入后台时,会分别截取 app 在 light 和 dark 模式下的截图,用于系统主题切换的同时对后台 app 预览视图进行切换,所以会切换多次 light/dark 模式。程序正常响应 change 事件即可,否则系统截取的图片可能会出现异常;如果确实有必要忽略这种情况下的 change 事件,可以在onHide后自行忽略。

uni.onHostThemeChange / uni.offHostThemeChange

监听 / 取消监听宿主(浏览器或小程序宿主)主题状态变化

onHostThemeChange 兼容性

| Web | 微信小程序 | Android | iOS | HarmonyOS | | :- | :- | :- | :- | :- | | 4.35 | 4.41 | x | x | 4.71 |

参数callback: (result: OnHostThemeChangeCallbackResult) => void,必填。

OnHostThemeChangeCallbackResult 的属性值

| 名称 | 类型 | 必备 | 兼容性 | 描述 | | :- | :- | :- | :-: | :- | | hostTheme | string | 是 | Android: x; iOS: x | 主题名称 |

hostTheme 合法值light(亮色模式)、dark(深色模式)。

返回值number(callbackId,用于注销监听)。

offHostThemeChange兼容性同为 Web: 4.35、微信小程序: 4.41、HarmonyOS: 4.71;参数id: number必填。

已废弃 API:uni.onThemeChange / uni.offThemeChange

已废弃,在 web、小程序上推荐使用onHostThemeChange/offHostThemeChange替代:

  • uni.onThemeChange(callback):监听系统主题状态变化,兼容性 Web: 4.0、微信小程序: 4.41、HarmonyOS: 4.71;回调参数OnThemeChangeCallbackResult.theme合法值为light/dark
  • uni.offThemeChange(callback):取消监听系统主题状态变化,兼容性同上。

完整示例:theme-change 页面与自动化测试

本仓库的示例工程在 src/pages/API/theme-change/theme-change.uvue 中提供了完整可运行的主题切换页面,其核心逻辑完整覆盖了上述 API 的典型用法:

  • bindOsThemeChange():App 端通过uni.onOsThemeChange注册系统主题监听,回调中更新osTheme
  • bindAppThemeChange():App 端用uni.onAppThemeChange监听应用主题;Web / 小程序端用uni.onHostThemeChange监听宿主主题,两端通过条件编译共用同一页面;
  • setAppTheme(value):调用uni.setAppTheme({ theme })success/fail回调中打印结果;
  • onReady:通过uni.getSystemInfo读取osThemeappThemehostTheme初始化展示数据(App 端对appTheme == 'auto'的情况结合osTheme换算真实主题),随后注册监听;
  • onUnload:分别调用uni.offAppThemeChangeuni.offOsThemeChangeuni.offHostThemeChange注销监听,避免页面销毁后回调泄漏;
  • 页面提供light/dark/auto三个 radio 选项,通过radioChange触发setAppTheme

与之配套的自动化测试 src/pages/API/theme-change/theme-change.test.js 验证了 setAppTheme 的行为链路:

it("check-set-app-theme", async () => { await page.callMethod('setAppTheme', "dark") await page.waitFor(300) expect(await page.data('appTheme')).toBe("dark") const image = await program.screenshot({ deviceShot: true }); expect(image).toSaveImageSnapshot(); })

测试先通过program.reLaunch进入/pages/API/theme-change/theme-change页面并读取originalTheme,随后调用页面暴露的setAppTheme('dark'),断言appTheme状态变为dark并截图比对,最后在afterAll中恢复原始主题——这也从工程角度印证了「setAppTheme → onAppThemeChange 回调 → 页面状态更新」的完整调用链。

示例项目参考

  1. hello uni-app x 示例目前使用媒体查询适配主题:其app.uvue、页面和组件样式中使用@media (prefers-color-scheme: light)@media (prefers-color-scheme: dark)定义不同主题下的样式(本仓库 src/common/uni.css 及各页面样式即为该方案的实例),pages/CSS/prefers-color-scheme页面提供了完整示例。
  2. test-theme 是一个基于无媒体查询、动态切换 class的示例项目,演示主题设置,适合需要兼容 HBuilderX 5.25 之前 App 平台或 VDOM 模式的场景。

总结:如何选择适配方案

| 需求 | 推荐方案 | 需要做的事 | | :- | :- | :- | | 只做 dark | 写死颜色 | 仅配置 pages.json 的 globalStyle,无需任何监听 | | 只跟随系统(web/小程序) | 媒体查询 + manifest darkmode |web/mp-weixin节点开启darkmode: true,样式用@media (prefers-color-scheme)| | 只跟随系统(App) | 媒体查询(5.25+ 蒸汽模式)或监听 osTheme |app.defaultAppTheme设为auto,结合uni.onOsThemeChange判断真实主题 | | App 独立切换 light/dark/auto |uni.setAppTheme+ 媒体查询(或监听 appTheme) | 配置theme.json,用setAppTheme切换,onAppThemeChange驱动业务逻辑 |

核心要点回顾:theme.json负责 pages.json 全局样式的亮暗切换,媒体查询负责 uvue 页面样式的自动匹配,setAppTheme/onAppThemeChange负责 App 独立主题的运行时控制;在 HBuilderX 5.25+ 蒸汽模式下优先使用媒体查询方案,可获得无闪烁、无 JS 开销的最优体验。

  • 示例工程
  • 前端
  • 移动开发
  • 跨平台

【免费下载链接】uni-app

A cross-platform framework using Vue.js

项目地址:https://gitcode.com/gh_mirrors/un/uni-app
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询