在舊版本的duxapp,支持主題功能,但是那時候的主體是靜態(tài)配置的,并不支持動態(tài)切換,新版本,在舊的靜態(tài)主題基礎(chǔ)上擴(kuò)展,實現(xiàn)了動態(tài)主題切換
舊版本靜態(tài)主題
在之前的版本中已經(jīng)支持主題功能,在用戶配置用,使用模塊的 theme 字段配置主題,像下面這樣
// configs/config/index.js
option: {
// 基礎(chǔ)模塊
duxapp: {
theme: {
primaryColor: '#CDDE00',
secondaryColor: '#FDD000',
successColor: '#34a853',
warningColor: '#fbbc05',
dangerColor: '#ea4335',
pageColor: '#fafbf8'
}
}
}
配置了這些主題參數(shù),會通過一個腳本轉(zhuǎn)化為scss變量被加入到全局scss變量中,就像下面這樣
$duxappPrimaryColor: #CDDE00;
$duxappSecondaryColor: #FDD000;
$duxappSuccessColor: #34a853;
$duxappDangerColor: #ea4335;
$duxappWarningColor: #fbbc05;
$duxappPageColor: #fafbf8;
然后你就能在任何scss文件中調(diào)用這些變量,例如 duxappStyle 的全局scss中調(diào)用這些變量,當(dāng)然也不局限于這個文件,任何的scss都能調(diào)用這些變量
// src/duxappStyle/app.scss
.bg-primary {
background-color: $duxappPrimaryColor;
}
.bg-secondary {
background-color: $duxappSecondaryColor;
}
.bg-success {
background-color: $duxappSuccessColor;
}
然后在你的項目中就可以調(diào)用這些全局類名就能獲得對應(yīng)的樣式
<View className='bg-primary' />
如果要編寫 style 的時候獲取這些主題參數(shù),可以像下面這樣
import { duxappTheme } from '@/duxapp'
<View style={{ backgroundColor: duxappTheme.primaryColor }} />
- 關(guān)于如何定制自己模塊的主題,查看這個文檔
新版本的動態(tài)主題
為了最小的升級成本,系統(tǒng)未對之前的主題系統(tǒng)進(jìn)行大改,而是在當(dāng)前的主題系統(tǒng)模式上進(jìn)行簡單調(diào)整就能使用
之前所有的內(nèi)容在新的主題系統(tǒng)中都是生效的,如果你要切換到動態(tài)主題,只需要在用戶配置中,配置多套主題即可
- 將當(dāng)前的模塊配置中的
theme移動到themes.light(每個模塊的配置都需要同樣的操作) - 在
themes里面新增一個主題配置dark,表示夜間模式的主題
:::info - 如果沒有指定
themeConfig.defaultlight將會作為默認(rèn)主題, - 在你配置
dark的主題的時候,如果和默認(rèn)配置light相同的配置,你可以不配置,只需要與light不同的部分即可
::: - 新增
themeConfig配置項目,參考下面的示例,需要在里面配置主題列表themes(必須配置) 其他三個選項為可選配配置,dark用于指定頁面模式主題,light用于指定白天模式主題,default指定默認(rèn)主題 - 只有當(dāng)夜間模式和白天模式兩個主題都存在的情況下系統(tǒng)才會跟隨系統(tǒng)主題進(jìn)行系統(tǒng)切換
- 除了
lightdark你還可以配置更多的主題,通過theme.setMode(主題)切換
const config = {
option: {
// 基礎(chǔ)模塊
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值,請勿使用純單詞 設(shè)置為數(shù)組將顯示一個漸變按鈕
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
動態(tài)切換
默認(rèn)情況下只需要你配置了 light 和 dark 兩個主題,程序就能跟隨系統(tǒng)自動切換
如果你需要手動切換,下面是一動態(tài)切換主題的示例代碼,參考這個進(jìn)行開發(fā),theme 是基礎(chǔ)模塊導(dǎo)出的工具
:::info
- 動態(tài)切換(包括自動切換)現(xiàn)在僅支持 小程序 H5端,其他平臺還在開發(fā)中
- 不支持的平臺會按照配置的默認(rèn)主題顯示
:::
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='主題切換當(dāng)前僅支持小程序和H5端,其他端還在努力開發(fā)中'
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>
}
如何實現(xiàn)的
動態(tài)主題在不同的平臺使用了不同的實現(xiàn)方案,具體來說,小程序 H5端使用了css變量,RN端使用了插件動態(tài)修改組件代碼實現(xiàn)動態(tài)切換
小程序 H5端
小程序 H5端 css 變量 的實現(xiàn)流程
- duxapp-cli 先將用戶配置的主題名稱進(jìn)行統(tǒng)計并存儲
- duxapp-cli 根據(jù)用戶主題配置生成主題scss文件
src/duxapp/userTheme/index.scss,這個文件會自動被 TopView組件引用 - 編寫一個
theme-loader將其插入到 webpack 的 loader 中,在處理 scss 之前,先解析動態(tài)主題,目的是將調(diào)用到scss主題變量的代碼,替換為調(diào)用css變量 - 主題系統(tǒng)通過一個改變類型動態(tài)切換css變量的流程
RN端
- duxapp-cli 先將用戶配置的主題名稱進(jìn)行統(tǒng)計并存儲
- duxapp-cli 根據(jù)用戶主題配置生成主題js文件
src/duxapp/userTheme/index.rn.js - 編寫一個
theme-loader將其插入到 webpack 的 loader 中,在處理 scss 之前,先解析動態(tài)主題,目的是將調(diào)用到scss主題變量的代碼,替換為調(diào)用css變量 - 使用 patch-package 修改了 rn 端相關(guān)插件,主要改變的功能是,解析
theme-loader生成的css變量,并替換成主題變量,并且將之前的styleSheet修改為函數(shù)的方式導(dǎo)出,函數(shù)接受一個主題名稱,傳入不同的主題名稱,返回不同的styleSheet - 修改插件,讓插件在函數(shù)組件的頭部,插入一個 hook ,這個 hook 會監(jiān)聽主題改變,并更新
styleSheet并且在主題更新后,重新渲染組件
因為 React 組件的編寫形式太過靈活多變,因此最后一步,在函數(shù)組件頭部插入一個hook的操作,并不一定所有組件都能插入,局具體使用的顯示參考這個說明
最后
duxapp的主題系統(tǒng)經(jīng)歷了從靜態(tài)配置到動態(tài)切換的演進(jìn)過程:
兼容性:新版本完美兼容舊版的靜態(tài)主題配置
靈活性:支持多主題配置和動態(tài)切換
跨平臺:針對不同平臺采用最優(yōu)實現(xiàn)方案
易用性:提供簡潔的API和配置方式
開發(fā)者可以根據(jù)項目需求選擇合適的主題方案,通過簡單的配置即可實現(xiàn)強(qiáng)大的主題功能。未來版本將繼續(xù)優(yōu)化各平臺的兼容性和性能表現(xiàn)。