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
以及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
。
写在最后
自此我们动态切换主题的效果就大功告成。
完整项目代码点击这里查看:https://codesandbox.io/s/antd-change-style-8rb12?file=/index.js
参考链接:
https://blog.csdn.net/m0_58016522/article/details/121751043
https://ant-design.gitee.io/changelog-cn
https://ant-design.gitee.io/docs/react/customize-theme-variable-cn
扩展阅读:
https://blog.csdn.net/m0_58016522/article/details/119104454