# 暗黑模式

uview-plus 已提供完整的暗黑模式能力,包含:

  • 主题变量(亮/暗两套语义变量)
  • 运行时主题状态(系统跟随、手动切换、事件通知)
  • 页面与组件的统一接入方式(upTheme* 计算属性与工具方法)
  • Root 根容器联动(全局背景与变量下发)

本文档对应近期暗黑模式架构升级后的方案,不是旧版“下载主题 scss 文件”流程。

# 1. 架构概览

当前实现采用三层结构:

  1. 主题变量层
    文件:src/uni_modules/uview-plus/libs/css/theme-vars-core.scss
    职责:定义 --up-* 语义变量,并分别提供:

    • 默认亮色变量
    • prefers-color-scheme: dark 自动切换变量
    • [data-up-theme='light'|'dark'] 强制主题变量
  2. 运行时主题层
    文件:src/uni_modules/uview-plus/libs/theme/theme.js
    职责:统一管理主题状态与切换逻辑,支持:

    • system | light | dark 偏好模式
    • 本地存储主题偏好
    • 系统主题变化监听(uni.onThemeChange
    • 同步 uni.$u.themeuni.$u.colorconfig.color
    • 发送全局事件 uThemeChange
  3. 页面接入层
    文件:src/uni_modules/uview-plus/libs/mixin/mixin.jssrc/App.up.vue
    职责:为页面和组件提供统一可用的主题能力,减少页面重复代码。

# 2. 可用 API

uview-plus 安装后可通过 uni.$u 使用以下接口:

// 强制切换当前主题(light / dark)
uni.$u.setTheme('dark')

// 设置主题偏好:system | light | dark
uni.$u.setThemePreference('system')

// 读取偏好与系统主题
uni.$u.getThemePreference()
uni.$u.getSystemTheme()

// 获取当前主题变量映射
uni.$u.getThemeVars()

主题切换后会触发全局事件:

uni.$on('uThemeChange', (payload) => {
  // payload.mode: light | dark
  // payload.vars: 当前变量字典
})

# 3. 页面推荐写法

页面默认可直接使用 mixin 提供的能力:

  • upThemeIsDark
  • upThemeVars
  • upThemePageStyle
  • upThemeCardStyle
  • upThemeVar(varName, fallback?)

示例:

<template>
  <view :style="upThemePageStyle">
    <view :style="upThemeCardStyle">内容区域</view>
  </view>
</template>

说明:

  • .vue / uvue 页面优先使用 CSS 变量(var(--up-xxx))能力。
  • nvue 不支持 CSS 变量时,使用 upThemeVar('--up-xxx', '#fallback') 获取运行时颜色。

# 4. Root 配合建议

若已启用 Root 注入(见 Root根组件),建议保留根容器统一背景与主题变量下发。
这样可以减少每个页面重复设置背景样式,避免出现“部分页面亮色、部分页面暗色”的断层。

# 5. 组件开发规范(暗黑适配)

组件样式建议遵循:

  1. 不直接写死颜色,优先使用语义变量
    例如:var(--up-content-color)var(--up-border-color)var(--up-bg-color)

  2. 组件内含状态色时,优先使用 --up-primary / --up-success / --up-warning / --up-error / --up-info 体系。

  3. 输入类组件必须关注三个对比度

    • 文本颜色
    • placeholder 颜色
    • 边框/背景颜色
  4. nvue 组件,统一通过运行时颜色映射做兜底。

# 6. 常见问题

# 6.1 页面仍是亮底

  • 检查是否使用了页面级硬编码背景色(覆盖了主题变量)。
  • 检查根容器是否正确挂载(App.up.vue + <UpRootView />)。
  • 检查主题切换是否实际触发(监听 uThemeChange 验证)。

# 6.2 组件在暗黑下“看不见”

常见原因:

  • 使用固定浅色文本(如 #333)但背景已变深。
  • placeholder 仍是浅灰,不符合暗底对比度。
  • 边框和背景使用同色,导致输入框轮廓消失。

建议优先替换为 --up-* 语义变量。

# 7. 迁移建议(从旧方案到新方案)

  1. 保留旧 theme.scss 兼容能力,但新页面优先使用运行时主题方案。
  2. 页面样式从“手工 if/else 颜色判断”迁移到 upThemePageStyle / upThemeVar
  3. 新增组件时直接按语义变量开发,避免后续二次暗黑改造成本。