在旧版本的duxapp,支持主题功能,但是那时候的主体是静态配置的,并不支持动态切换,新版本,在旧的静态主题基础上扩展,实现了动态主题切换

旧版本静态主题

在之前的版本中已经支持主题功能,在用户配置用,使用模块的 theme 字段配置主题,像下面这样

// configs/config/index.js
option: {
// 基础模块
duxapp: {
theme: {
primaryColor: '#CDDE00',
secondaryColor: '#FDD000',
successColor: '#34a853',
warningColor: '#fbbc05',
dangerColor: '#ea4335',
pageColor: '#fafbf8'
}
}
}

配置了这些主题参数,会通过一个脚本转化为scss变量被加入到全局scss变量中,就像下面这样

$duxappPrimaryColor: #CDDE00;
$duxappSecondaryColor: #FDD000;
$duxappSuccessColor: #34a853;
$duxappDangerColor: #ea4335;
$duxappWarningColor: #fbbc05;
$duxappPageColor: #fafbf8;

然后你就能在任何scss文件中调用这些变量,例如 duxappStyle 的全局scss中调用这些变量,当然也不局限于这个文件,任何的scss都能调用这些变量

// src/duxappStyle/app.scss
.bg-primary {
background-color: $duxappPrimaryColor;
} .bg-secondary {
background-color: $duxappSecondaryColor;
} .bg-success {
background-color: $duxappSuccessColor;
}

然后在你的项目中就可以调用这些全局类名就能获得对应的样式

<View className='bg-primary' />

如果要编写 style 的时候获取这些主题参数,可以像下面这样

import { duxappTheme } from '@/duxapp'

<View style={{ backgroundColor: duxappTheme.primaryColor }} />
  • 关于如何定制自己模块的主题,查看这个文档

新版本的动态主题

为了最小的升级成本,系统未对之前的主题系统进行大改,而是在当前的主题系统模式上进行简单调整就能使用

之前所有的内容在新的主题系统中都是生效的,如果你要切换到动态主题,只需要在用户配置中,配置多套主题即可

  • 将当前的模块配置中的 theme 移动到 themes.light (每个模块的配置都需要同样的操作)
  • themes 里面新增一个主题配置 dark,表示夜间模式的主题

    :::info
  • 如果没有指定 themeConfig.default light将会作为默认主题,
  • 在你配置 dark 的主题的时候,如果和默认配置 light 相同的配置,你可以不配置,只需要与 light 不同的部分即可

    :::
  • 新增 themeConfig 配置项目,参考下面的示例,需要在里面配置主题列表 themes (必须配置) 其他三个选项为可选配配置,dark 用于指定页面模式主题,light 用于指定白天模式主题,default 指定默认主题
  • 只有当夜间模式和白天模式两个主题都存在的情况下系统才会跟随系统主题进行系统切换
  • 除了 light dark 你还可以配置更多的主题,通过 theme.setMode(主题) 切换
const config = {
option: {
// 基础模块
duxapp: {
themeConfig: {
themes: {
light: {
name: '明亮主题',
color: '#fff'
},
dark: {
name: '暗黑主题',
color: '#333'
}
},
// dark: 'dark',
// light: 'light',
// default: 'light'
},
themes: {
light: {
primaryColor: '#E70012',
secondaryColor: '#0092e8',
successColor: '#34a853',
warningColor: '#fbbc05',
dangerColor: '#ea4335',
pageColor: '#F7F9FC', textColor1: '#373D52',
textColor2: '#73778E',
textColor3: '#A1A6B6',
textColor4: '#FFF',
header: {
color: '#fff', // 仅支持rgb hex值,请勿使用纯单词 设置为数组将显示一个渐变按钮
textColor: '#000', // 文本颜色
showWechat: true, // 微信公众号是否显示header
showWap: true, // h5是否显示header
}
},
dark: {
pageColor: '#1E1E1E', whiteColor: '#181818',
blackColor: '#fff',
lineColor: '#1F1F1F', textColor1: '#FFF',
textColor2: '#A1A6B6',
textColor3: '#73778E',
textColor4: '#373D52',
header: {
color: '#121212',
textColor: '#fff'
},
loading: {
dark: '#fff',
blank: '#7a7a7a'
}
}
}
},
duxui: {
themes: {
light: {
button: {
radiusType: 'round'
}
},
dark: {
tabBar: {
nameColor: '#888',
nameHoverColor: '#fff'
}
}
}
}
}
} export default config

动态切换

默认情况下只需要你配置了 lightdark 两个主题,程序就能跟随系统自动切换

如果你需要手动切换,下面是一动态切换主题的示例代码,参考这个进行开发,theme 是基础模块导出的工具

:::info

  • 动态切换(包括自动切换)现在仅支持 小程序 H5端,其他平台还在开发中
  • 不支持的平台会按照配置的默认主题显示

    :::
import { Header, ScrollView, TopView, GroupList, theme, Button } from '@/duxuiExample'

export default function ThemeExample() {

  const mode = theme.useMode(true)

  const modes = theme.useModes()

  return <TopView>
<Header title='Theme' />
<ScrollView>
<GroupList>
<GroupList.Item title='主题切换功能' desc='主题切换当前仅支持小程序和H5端,其他端还在努力开发中'
className='gap-3'
>
{
modes.map(item => <Button
type='primary'
plain={item.mode !== mode}
key={item.name}
onClick={() => item.switch()}
size='l'
>{item.name}</Button>)
}
</GroupList.Item>
</GroupList>
</ScrollView>
</TopView>
}

如何实现的

动态主题在不同的平台使用了不同的实现方案,具体来说,小程序 H5端使用了css变量,RN端使用了插件动态修改组件代码实现动态切换

小程序 H5端

小程序 H5端 css 变量 的实现流程

  • duxapp-cli 先将用户配置的主题名称进行统计并存储
  • duxapp-cli 根据用户主题配置生成主题scss文件 src/duxapp/userTheme/index.scss,这个文件会自动被 TopView组件引用
  • 编写一个 theme-loader 将其插入到 webpack 的 loader 中,在处理 scss 之前,先解析动态主题,目的是将调用到scss主题变量的代码,替换为调用css变量
  • 主题系统通过一个改变类型动态切换css变量的流程

RN端

  • duxapp-cli 先将用户配置的主题名称进行统计并存储
  • duxapp-cli 根据用户主题配置生成主题js文件 src/duxapp/userTheme/index.rn.js
  • 编写一个 theme-loader 将其插入到 webpack 的 loader 中,在处理 scss 之前,先解析动态主题,目的是将调用到scss主题变量的代码,替换为调用css变量
  • 使用 patch-package 修改了 rn 端相关插件,主要改变的功能是,解析 theme-loader 生成的css变量,并替换成主题变量,并且将之前的 styleSheet 修改为函数的方式导出,函数接受一个主题名称,传入不同的主题名称,返回不同的 styleSheet
  • 修改插件,让插件在函数组件的头部,插入一个 hook ,这个 hook 会监听主题改变,并更新 styleSheet 并且在主题更新后,重新渲染组件

因为 React 组件的编写形式太过灵活多变,因此最后一步,在函数组件头部插入一个hook的操作,并不一定所有组件都能插入,局具体使用的显示参考这个说明

最后

duxapp的主题系统经历了从静态配置到动态切换的演进过程:

  • 兼容性:新版本完美兼容旧版的静态主题配置

  • 灵活性:支持多主题配置和动态切换

  • 跨平台:针对不同平台采用最优实现方案

  • 易用性:提供简洁的API和配置方式

开发者可以根据项目需求选择合适的主题方案,通过简单的配置即可实现强大的主题功能。未来版本将继续优化各平台的兼容性和性能表现。

主题开发文档

开发文档

GitHub

duxapp中主题系统是如何实现动态切换的的更多相关文章

  1. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  2. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  3. Pytest测试框架一键动态切换环境思路及方案

    前言 在上一篇文章<Pytest fixture及conftest详解>中,我们介绍了fixture的一些关键特性.用法.作用域.参数等,本篇文章将结合fixture及conftest实现 ...

  4. IOS中调用系统的电话、短信、邮件、浏览功能

    iOS开发系列--通讯录.蓝牙.内购.GameCenter.iCloud.Passbook系统服务开发汇总 2015-01-13 09:16 by KenshinCui, 26990 阅读, 35 评 ...

  5. 总结一下Android中主题(Theme)的正确玩法

    在AndroidManifest.xml文件中有<application android:theme="@style/AppTheme">,其中的@style/AppT ...

  6. Silverlight4中实现Theme的动态切换

    Silverlight一般用来开发一些企业的应用系统,如果用户一直面对同一种风格的页面,时间长了难免厌烦,所以一般都会提供好几种风格及Theme供用户选中,下面就来说一下如何在不重新登录系统的情况下, ...

  7. 在Linux中创建静态库.a和动态库.so

    转自:http://www.cnblogs.com/laojie4321/archive/2012/03/28/2421056.html 在Linux中创建静态库.a和动态库.so 我们通常把一些公用 ...

  8. 【转载】总结一下Android中主题(Theme)的正确玩法

    http://www.cnblogs.com/zhouyou96/p/5323138.html 总结一下Android中主题(Theme)的正确玩法 在AndroidManifest.xml文件中有& ...

  9. linux中C的静态库和动态库分析

    从开始学C语言写第一个"hello world"历程到现在,我依然困惑于到底这个程序完整的执行流程是什么样的.不过,现在我正在尝试一点一点的揭开它的面纱.现在,我尝试分析linux ...

  10. QT皮肤系统的动态切换

    应用需求: 提供皮肤切换选项,在不重启应用程序的情况下实现皮肤的动态切换. 理论基础: 1) 图片资源是如何被利用的 这里先简要说明一下实现原理,皮肤的动态切换其关键在于图片资源的加载方式.QT中每个 ...

随机推荐

  1. B1051 复数乘法

    描述 复数可以写成 (A+Bi) 的常规形式,其中 A 是实部,B 是虚部,i 是虚数单位,满足 i^​2=−1:也可以写成极坐标下的指数形式 (R×e​(Pi)​ ),其中 R 是复数模,P 是辐角 ...

  2. TenantLineInnerInterceptor源码解读

    一.引言 TenantLineInnerInterceptor是MyBatis-Plus中的一个拦截器类,位于com.baomidou.mybatisplus.extension.plugins.in ...

  3. Style:用法,多样性,全局样式与资源字典

    Style:用法,多样性,全局样式与资源字典 本文同时为b站WPF课程的笔记,相关示例代码 对应06~08 前言 大部分能够想到的属性,xaml里面都是自带了的.可以多去网络上搜一搜.比如说高度.宽度 ...

  4. MYSQL优化学习总结

    mysql学习小结---索引的使用及优化 1. 索引那些事 1.1 复合索引 复合索引是指:包含一个或者多个列的索引.但复合索引的触发是有条件的. 假设我们现在有一个复合索引a,a中包含了三个列(id ...

  5. Android Studio 虚拟机一直黑屏原因及解决办法

    虚拟机一直黑屏原因: android模拟器在创建时,一般默认设置为热启动,所以每次关闭模拟器时,会提示保存当前运行界面状态,若选择取消,则下一次启动会以最近一次保存的状态启动显示.如果某次关闭时保存的 ...

  6. redis碰到的问题

    SpringBoot整合redis 连接报错: Unable to connect to Redis; nested exception is org.springframework.data.red ...

  7. 又TM遇到傻B了

    一想到自己的收藏还有可能被傻逼用到,我TM更蛋疼了...傻逼千千万

  8. ChunJun Meetup演讲分享 | 基于袋鼠云开源框架的数仓一体化建设探索

    8月27日,ChunJun社区联合OceanBase社区举办开源线下Meetup,围绕「构建新型的企业级数仓解决方案」主题,多位技术大牛和现场爱好者汇聚一堂,畅所欲言. 会上,袋鼠云大数据引擎开发专家 ...

  9. wc记录

    WC记录 咋可 随机化 CF1746F 给每个值随机成\(0/1\),然后查询区间内的所有数的和是否\(\equiv0\mod k\) 考虑错误率,对于一个不合法的权值,设其有\(r\)个,考虑区间内 ...

  10. C++ pair对组 学习总结

    ----------------------------------------------pair对组 对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型两个值可以分别用pair的 ...