React + Antd实现动态切换主题功能_类名

前端早茶专注前端,一起结伴同行,紧跟业界发展步伐~

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​​样式控制按钮的背景色及边框线颜色。如下图:

 React + Antd实现动态切换主题功能_类名_02

 

 

  ant-btn-primary样式


对于类名​​ant-btn​​​以及​​ant-btn-primary​​​,​​ant​​实际上作为样式的前缀。而我们如果动态的将样式类名中的前缀统一替换成其他的字符串,就实现了主题切换的效果。

 

具体实现

  1. 依据官方文档,通过​​ConfigProfider​​​在顶层修改​​prefixCls​​:

import { ConfigProvider } from 'antd';

export default () => (
<ConfigProvider prefixCls="custom">
<MyApp />
</ConfigProvider>
);

  1. 编译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

  1. 按照步骤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;

  1. ​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"));


最终效果

 

React + Antd实现动态切换主题功能_ide_03React + Antd实现动态切换主题功能_ide_04

 

 

 

 

最终效果

从上图我们可以看到,radio单选框选择ant style时,此时页面渲染主题色为ant默认的蓝色,而radio选择custom style后,页面渲染的主题色已经动态切换成我们修改后的红色。通过浏览器调试窗口,我们可以发现,按钮的class类名前缀为​​ant​​​,选择custom style后,class类名前缀切换为​​custom​​。

 默认样式

React + Antd实现动态切换主题功能_ide_05

 修改后的样式

 

React + Antd实现动态切换主题功能_css_06

 

 

 

 

写在最后

自此我们动态切换主题的效果就大功告成。

欢迎关注前端早茶,与广东靓仔携手共同进阶

React + Antd实现动态切换主题功能_类名

前端早茶专注前端,一起结伴同行,紧跟业界发展步伐~