前言
在前一篇文章中(http://www.itdecent.cn/p/13421246b97d)初略的講解了通過ConfigProvider全局化配置prefixCls的方式來動態(tài)切換部分主題樣式配置,文章中只是通過修改部分顏色(如primary顏色)來初步展示了效果,可能效果不甚理想。
對于實際項目開發(fā)中,其中有一類需求比較多的就是動態(tài)切換默認(亮色)主題與暗黑色主題,在ant-design官網(wǎng)有一個官方的demo可以參考:https://github.com/gzgogo/antd-theme 。下面我通過一個小demo,來展示一下默認主題與暗黑色主題切換功能的開發(fā)步驟。
實現(xiàn)思路
首先我的思路還是通過ConfigProvider全局化配置prefixCls的方式來修改ant design樣式的prefix,即默認主題通過類名前綴custom-default來控制樣式,而暗色主題通過類名前綴custom-dark來控制樣式。
1. 編譯默認主題css文件
```shell
# 指定prefix為custom-default
# 源文件為antd.less
$ lessc --js --modify-var="ant-prefix=custom-default" node_modules/antd/dist/antd.less custom-default.css
```
按照上述步驟的命令會生成一個``custom-default.css``的文件,該文件為默認主題的樣式文件,在該文件內(nèi)容中有一段如下樣式:
```css
body {
margin: 0;
color: rgba(0, 0, 0, 0.85);
font-size: 14px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
font-variant: tabular-nums;
line-height: 1.5715;
background-color: #fff;
font-feature-settings: 'tnum';
}
```
這段內(nèi)容主要是控制body區(qū)塊的樣式,我們將這段樣式做如下修改
```css
body .custom-default { /*添加.custom-default子樣式,作用我們在下文中會說明*/
margin: 0;
color: rgba(0, 0, 0, 0.85);
font-size: 14px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
font-variant: tabular-nums;
line-height: 1.5715;
background-color: #fff;
font-feature-settings: 'tnum';
}
```
2. 同上述步驟1的處理,編譯暗黑色主題css文件
```shell
# 指定prefix為custom-dark
# 源文件為antd.dark.less
$ lessc --js --modify-var="ant-prefix=custom-dark" node_modules/antd/dist/antd.dark.less custom-dark.css
```
同樣的,生成的暗黑色樣式文件``custom-dark.css``中有這么一段:
```css
body {
margin: 0;
color: rgba(255, 255, 255, 0.85);
font-size: 14px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
font-variant: tabular-nums;
line-height: 1.5715;
background-color: #000;
font-feature-settings: 'tnum';
}
```
我們也做類似的修改:
```css
body .custom-dark { /*添加.custom-dark 子樣式,作用我們在下文中會說明*/
margin: 0;
color: rgba(255, 255, 255, 0.85);
font-size: 14px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
font-variant: tabular-nums;
line-height: 1.5715;
background-color: #000;
font-feature-settings: 'tnum';
}
```
3. index.js中引入上述兩個步驟生成的css文件
index.js完整代碼如下:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import {
Button,
Calendar,
Card,
DatePicker,
Empty,
Layout,
Radio,
Space
} from "antd";
import { DownloadOutlined } from "@ant-design/icons";
import { ConfigProvider } from "antd";
// import "antd/dist/antd.css";
import "./custom-default.css"; // 引入custom-default.css 以及 custom-dark.css
import "./custom-dark.css";
import "./index.css";
const TestComponent = () => {
const [prefix, setPrefix] = useState("custom-default");
const handlePrefixChange = (e) => {
setPrefix(e.target.value);
};
return (
<ConfigProvider prefixCls={prefix}>
<div className={`App ${prefix}`} style={{ height: "100%" }}>
<Layout style={{ height: "100%" }}>
<Layout.Content>
<Space>
Change Theme:
<Radio.Group onChange={handlePrefixChange} value={prefix}>
<Radio value="custom-default">default Style</Radio>
<Radio value="custom-dark">dark Style</Radio>
</Radio.Group>
</Space>
<br />
<Space>
<DatePicker />
<Empty />
<Card
title="Default size card"
extra={<a href="#">More</a>}
style={{ width: 300 }}
>
<p>Card content</p>
<p>Card content</p>
<p>Card content</p>
</Card>
</Space>
<br />
<Space>
<Radio.Group>
<Radio.Button value="large">Large</Radio.Button>
<Radio.Button value="default">Default</Radio.Button>
<Radio.Button value="small">Small</Radio.Button>
</Radio.Group>
<br />
<br />
<Button type="primary">Primary</Button>
<Button>Default</Button>
<Button type="dashed">Dashed</Button>
<br />
<Button type="link">Link</Button>
<br />
<Button type="primary" icon={<DownloadOutlined />} />
<Button
type="primary"
shape="circle"
icon={<DownloadOutlined />}
/>
<Button
type="primary"
shape="round"
icon={<DownloadOutlined />}
/>
<Button type="primary" shape="round" icon={<DownloadOutlined />}>
Download
</Button>
<Button type="primary" icon={<DownloadOutlined />}>
Download
</Button>
</Space>
<br />
<Space>
<Calendar fullscreen={false} />
</Space>
</Layout.Content>
</Layout>
</div>
</ConfigProvider>
);
};
ReactDOM.render(<TestComponent />, document.getElementById("root"));
其中比較關(guān)鍵的一點是31行左右的<div className={`App ${prefix}`} style={{height: '100%'}}>,切換至默認主題時,該div渲染的樣式類名為App custom-default,切換至暗黑色主題時,div渲染的樣式類名為App custom-dark,其中custom-default及custom-dark分別由上述步驟1及步驟2中編譯生成的css文件對應(yīng)的 body .custom-default及body .custom-dark控制樣式。此兩段樣式主要控制背景色以及字體顏色,分別由兩段樣式控制的,原因是避免樣式污染,即如果不做修改,后引入的css文件中的body樣式,會覆蓋前引入的css文件中的body樣式。
另外部分原理可以參考文章:http://www.itdecent.cn/p/13421246b97d
最終效果

寫在最后
動態(tài)切換默認主題和暗黑色主題主要原理和前篇文章類似:(http://www.itdecent.cn/p/13421246b97d),有需要的可以參考。
上述文章中,對于一些前端知識方面的解釋,可能不是很專業(yè)。(其實我是個后端o(∩_∩)o )
完整代碼可以點擊這里查看:https://codesandbox.io/s/antd-change-style-dark-gjurt?file=/index.js
參考鏈接:
https://blog.csdn.net/m0_58016522/article/details/122067153
https://ant-design.gitee.io/docs/react/customize-theme-cn
https://blog.csdn.net/m0_58016522/article/details/121751043