前端早茶专注前端,一起结伴同行,紧跟业界发展步伐~
React + Antd 实现动态切换主题功能
前言
最近去ant design官网查阅资料,发现ant design最新版本已经更新到了4.17.x
,于是比较粗略的看了一下最近几个4.17.x
版本的更新日志,发现4.17.0
版本更新了大量内容(点击查看4.17.0版本更新日志),在这其中比较吸引我注意点一点是实现了动态主题的功能。不过点看动态主题的文档,却标明着是实验性的功能,真是一个大写的囧。。。
在4.17.0
之前的版本里,实现动态主题的方法比较麻烦(也可能是我孤陋寡闻),通常是通过修改less变量的方式实现的,我个人觉得还是比较繁琐的。在4.17.0
版本后官方开始支持动态切换主题的功能,这点让我感到比较欣慰。
注意事项
以下摘自官方文档的描述:
- 该功能通过动态修改 CSS Variable 实现,因而在 IE 中页面将无法正常展示。请先确认你的用户环境是否需要支持 IE。
- 该功能在 antd@4.17.0-alpha.0 版本起支持。
实现原理
动态切换主题的功能是,通过ConfigProvider
全局化配置,设置统一的样式前缀,具体ConfigProvider
相关文档可以看这里:https://ant-design.gitee.io/components/config-provider-cn/#API。
举个例子,antd按钮控件,参数type
设置为'primary'
后,实际渲染出来后,会添加上class="ant-btn ant-btn-primary"
的属性,其中ant-btn-primary
样式控制按钮的背景色及边框线颜色。如下图:
ant-btn-primary样式
对于类名ant-btn
以及ant-btn-primary
,ant
实际上作为样式的前缀。而我们如果动态的将样式类名中的前缀统一替换成其他的字符串,就实现了主题切换的效果。
具体实现
- 依据官方文档,通过
ConfigProfider
在顶层修改prefixCls
:
import { ConfigProvider } from 'antd';
export default () => (
<ConfigProvider prefixCls="custom">
<MyApp />
</ConfigProvider>
);
- 编译less
由于步骤1中,通过ConfigProfider
将样式类名前缀调整为custom
,我们需要重新通过lessc命令,将antd的默认样式less文件,重新编译生成一份css文件。※注意:如果未安装less,则需要安装less:npm install -g less
lessc --modify-var="ant-prefix=custom" node_modules/antd/dist/antd.variable.less custom.css
如果单单按照官方文档中的操作执行上述命令,控制台会报错:
SyntaxError: Inline JavaScript is not enabled. Is it set in your options? in D:\workspace\workspace_for_java\SPB-LERN\web-react-ts\node_modules\antd\lib\style\color\bezierEasing.less on line 110, column 1:
109 // https://github.com/ant-design/ant-motion/issues/44
110 .bezierEasingMixin();
111
因为默认lessc命令未开启javascript功能,需要通过参数开启javascript功能,参考链接:https://lesscss.org/usage/#less-options-enable-inline-javascript-deprecated-。将上述命令添加--js
参数后执行即可:
lessc --js --modify-var="ant-prefix=custom" node_modules/antd/dist/antd.variable.less custom.css
- 按照步骤2中的命令,会生成一个
custom.css
,由于文件过于庞大,截取几段内容如下:
html {
--custom-primary-color: #1890ff;
--custom-primary-color-hover: #40a9ff;
--custom-primary-color-active: #096dd9;
--custom-primary-color-outline: rgba(24, 144, 255, 0.2);
--custom-primary-1: #e6f7ff;
--custom-primary-2: #bae7ff;
--custom-primary-3: #91d5ff;
--custom-primary-4: #69c0ff;
--custom-primary-5: #40a9ff;
--custom-primary-6: #1890ff;
--custom-primary-7: #096dd9;
--custom-primary-color-deprecated-pure: ;
--custom-primary-color-deprecated-l-35: #cbe6ff;
--custom-primary-color-deprecated-l-20: #7ec1ff;
--custom-primary-color-deprecated-t-20: #46a6ff;
--custom-primary-color-deprecated-t-50: #8cc8ff;
--custom-primary-color-deprecated-f-12: rgba(24, 144, 255, 0.12);
--custom-primary-color-active-deprecated-f-30: rgba(230, 247, 255, 0.3);
--custom-primary-color-active-deprecated-d-02: #dcf4ff;
/* 以下内容略去 */
其中第二行中的--custom-primary-color
即为primary的样色,默认为antd默认的蓝色,用于测试效果,我们可以将该改色修改为红色:
html {
--custom-primary-color: #ff0000;/* 修改为红色 */
--custom-primary-color-hover: #40a9ff;
-
index.js
文件引入上述步骤中的custom.css
文件。※注意:默认的antd样式文件antd/dist/antd.css
也需要引入。index.js
文件完整代码如下:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Button, DatePicker, Radio, Space, version } from "antd";
import { ConfigProvider } from "antd";
import "antd/dist/antd.css"; // antd默认样式文件
import "./custom.css"; // 修改后的样式文件
import "./index.css";
const TestComponent = () => {
const [prefix, setPrefix] = useState("ant");
const handlePrefixChange = (e) => {
setPrefix(e.target.value);
};
return (
// ConfigProvider修改prefixCls
<ConfigProvider prefixCls={prefix}>
<div className="App">
<h1>
<Space>
Change Theme:
{/* radio动态修改prefix */}
<Radio.Group onChange={handlePrefixChange} value={prefix}>
<Radio value="ant">Ant Style</Radio>
<Radio value="custom">Custom Style</Radio>
</Radio.Group>
</Space>
</h1>
<h1>antd version: {version}</h1>
<DatePicker />
<Button type="primary" style={{ marginLeft: 8 }}>
Primary Button
</Button>
</div>
</ConfigProvider>
);
};
ReactDOM.render(<TestComponent />, document.getElementById("root"));
最终效果
最终效果
从上图我们可以看到,radio单选框选择ant style时,此时页面渲染主题色为ant默认的蓝色,而radio选择custom style后,页面渲染的主题色已经动态切换成我们修改后的红色。通过浏览器调试窗口,我们可以发现,按钮的class类名前缀为ant
,选择custom style后,class类名前缀切换为custom
。
默认样式
修改后的样式
写在最后
自此我们动态切换主题的效果就大功告成。
欢迎关注前端早茶,与广东靓仔携手共同进阶
前端早茶专注前端,一起结伴同行,紧跟业界发展步伐~