三步完成Ant Design Pro 的主题切换

9,428 阅读2分钟

Ant Design Pro 是一个非常优秀的开箱即用的中台前端/设计解决方案,私以为有些地方过度封装,当然这是见仁见智的看法。项目中遇到需要切换主题的需求,研究了一下,最后得到了比较完美的结果。

主题切换分为两个部分,一个是 Ant Design 组件的主题切换,另一个是自定义组件的主题切换。下面分为两部分一个个解决。

Ant Design组件

在 V2 版本中,主题切换的功能是有Bug的,官方也不推荐使用,但是在 V4 版本中解决了此问题,经过本人测试,V4 版本的解决方案同时适应于 V2 版本。

首先,安装 umi-plugin-antd-theme 这个插件:

npm i umi-plugin-antd-theme

这个插件的原理就是根据你的配置项,将 Ant Design 所有组件中的变量替换成你自定义的,生成多个主题.css文件,放置在theme文件夹下。

  • V2 版本

将下面的代码复制到config/config.*.js文件中去,最后如下:

const plugins = [
  [
    'umi-plugin-react',
    ...
  ],
  [
    'umi-plugin-antd-theme',
    {
      theme: [
        {
          fileName: 'theme1.css',
          key:'theme1',
          modifyVars: {
            '@primary-color': '#13C2C2',
            '@menu-dark-color': '#324444',
            '@menu-dark-bg': '#5A5A5A',
          },
        },
        {
          fileName: 'theme2.css',
          key:'theme2',
          modifyVars: {
            '@primary-color': '#4992BF',
            '@menu-dark-color': '#9B9B9B',
            '@menu-dark-bg': '#3A3A3A',
          },
        },
      ],
      // 是否压缩css
      min: true,
      // css module
      isModule: true,
      // 忽略 antd 的依赖
      ignoreAntd: false,
      // 忽略 pro-layout
      ignoreProLayout: false,
      // 不使用缓存
      cache: true,
    },
  ],
];
  • v4 版本 在config/themePluginConfig.ts添加类似代码:
export default {
  theme: [
    ...
   {
          fileName: 'theme1.css',
          key:'theme1',
          modifyVars: {
            '@primary-color': '#13C2C2',
            '@menu-dark-color': '#324444',
            '@menu-dark-bg': '#5A5A5A',
          },
        },
        {
          fileName: 'theme2.css',
          key:'theme2',
          modifyVars: {
            '@primary-color': '#4992BF',
            '@menu-dark-color': '#9B9B9B',
            '@menu-dark-bg': '#3A3A3A',
          },
        },
  ],
};

自定义组件

global.less文件中,添加如下代码:

.body-wrap-theme1 {
    // theme1下的全局变量在此定义
    --font-color: #000000;
    --bg-color: #011313;
}

.body-wrap-theme2 {
    // theme2下的全局变量在此定义
    --font-color: #ffffff;
    --bg-color: #ffffff;
}

自定义组件的index.less中用法如下:

.flatButton{
  color: var(--font-color);
  backgroud: var(--bg-color);
}

主题切换

在主题切换的方法中添加如下代码,可以根据自己需要进行修改,比如添加从本地获取上次主题配置项等:

theme1 = true;
onClick = () => {
    let styleLink = document.getElementById("theme-style");
    let body = document.getElementsByTagName('body')[0];
    if (styleLink) { // 假如存在id为theme-style 的link标签,直接修改其href
      if (this.theme1) {
        styleLink.href = '/theme/theme1.css';  // 切换 ant design 组件主题
        body.className = "body-wrap-theme1";  // 切换自定义组件的主题
      } else {
        styleLink.href = '/theme/theme2.css';
        body.className = "body-wrap-theme2";
      }
      this.theme1 = !this.theme1;
    } else { // 不存在的话,则新建一个
      styleLink = document.createElement('link');
      styleLink.type = 'text/css';
      styleLink.rel = 'stylesheet';
      styleLink.id = 'theme-style';
      if (this.theme1) {
        styleLink.href = '/theme/theme1.css';
        body.className = "body-wrap-theme1";
      } else {
        styleLink.href = '/theme/theme2.css';
        body.className = "body-wrap-theme2";
      }
      this.theme1 = !this.theme1;
      document.body.append(styleLink);
    }
  }

这个实现的思路容易理解,一个是替换CSS文件,一个是css自带的 var替换变量。PS:感谢同事梁老师的帮助

JerryMissTom是我的 GitHub 地址,欢迎Follow