# 暗黑模式
uview-plus 已提供完整的暗黑模式能力,包含:
- 主题变量(亮/暗两套语义变量)
- 运行时主题状态(系统跟随、手动切换、事件通知)
- 页面与组件的统一接入方式(
upTheme*计算属性与工具方法) - Root 根容器联动(全局背景与变量下发)
本文档对应近期暗黑模式架构升级后的方案,不是旧版“下载主题 scss 文件”流程。
# 1. 架构概览
当前实现采用三层结构:
主题变量层
文件:src/uni_modules/uview-plus/libs/css/theme-vars-core.scss
职责:定义--up-*语义变量,并分别提供:- 默认亮色变量
prefers-color-scheme: dark自动切换变量[data-up-theme='light'|'dark']强制主题变量
运行时主题层
文件:src/uni_modules/uview-plus/libs/theme/theme.js
职责:统一管理主题状态与切换逻辑,支持:system | light | dark偏好模式- 本地存储主题偏好
- 系统主题变化监听(
uni.onThemeChange) - 同步
uni.$u.theme、uni.$u.color、config.color - 发送全局事件
uThemeChange
页面接入层
文件:src/uni_modules/uview-plus/libs/mixin/mixin.js、src/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 提供的能力:
upThemeIsDarkupThemeVarsupThemePageStyleupThemeCardStyleupThemeVar(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. 组件开发规范(暗黑适配)
组件样式建议遵循:
不直接写死颜色,优先使用语义变量
例如:var(--up-content-color)、var(--up-border-color)、var(--up-bg-color)。组件内含状态色时,优先使用
--up-primary / --up-success / --up-warning / --up-error / --up-info体系。输入类组件必须关注三个对比度
- 文本颜色
- placeholder 颜色
- 边框/背景颜色
对
nvue组件,统一通过运行时颜色映射做兜底。
# 6. 常见问题
# 6.1 页面仍是亮底
- 检查是否使用了页面级硬编码背景色(覆盖了主题变量)。
- 检查根容器是否正确挂载(
App.up.vue+<UpRootView />)。 - 检查主题切换是否实际触发(监听
uThemeChange验证)。
# 6.2 组件在暗黑下“看不见”
常见原因:
- 使用固定浅色文本(如
#333)但背景已变深。 - placeholder 仍是浅灰,不符合暗底对比度。
- 边框和背景使用同色,导致输入框轮廓消失。
建议优先替换为 --up-* 语义变量。
# 7. 迁移建议(从旧方案到新方案)
- 保留旧
theme.scss兼容能力,但新页面优先使用运行时主题方案。 - 页面样式从“手工 if/else 颜色判断”迁移到
upThemePageStyle / upThemeVar。 - 新增组件时直接按语义变量开发,避免后续二次暗黑改造成本。