【React】antd在线换主题

前言

  • 最近整个antd在线换主题功能,结果发现官方居然没有这功能。只能一开始写死。后来研究了几种方法,记录一下。

方案一

  • 换less
  • 使用antd-theme-generator先生成less颜色变量,在index.html中使用less加载,在js中切换less变量。
  • 请注意antd的位置,因为我这项目是lerna的所以位置跟一般的不太一样。
const path = require('path');
const {
    
     generateTheme } = require('antd-theme-generator');

const options = {
    
    
  stylesDir: path.join(__dirname, '../src/styles'),
  antDir: path.join(__dirname, '../../../node_modules/antd'),
  varFile: path.join(__dirname, '../src/styles/variables.less'),
  mainLessFile: path.join(__dirname, '../src/styles/index.less'),
  themeVariables: [
    '@primary-color',
    '@secondary-color',
    '@text-color',
    '@text-color-secondary',
    '@heading-color',
    '@layout-body-background',
    '@layout-header-background',
    '@border-radius-base',
  ],
  outputFilePath: path.join(__dirname, '../public/color.less'),
};

generateTheme(options)
  .then((less) => {
    
    
    console.log('Theme generated successfully');
  })
  .catch((error) => {
    
    
    console.log('Error', error);
  });

  • variable里引入antd的
// variables.less
@import "~antd/lib/style/themes/default.less";
@primary-color: #1890ff;
  • 使用node 生成color文件后,在index中加载他:
  <link
      rel="stylesheet/less"
      type="text/css"
      href="<%= context.config.publicPath + 'color.less'%>"
      rel="external nofollow"
    />
  • 将less挂到 window上
  <script>
      window.less = {
    
    
        async: false,
        env: 'development',
        javascriptEnabled: true
      };
    </script>
    <script
      type="text/javascript"
      src="https://cdnjs.cloudflare.com/ajax/libs/less.js/3.11.1/less.min.js"
    ></script>
 
  • js中使用切换less变量即可:
 const [theme, setTheme] = React.useState('default');

  const setThemeColor = (theme: 'default' | 'dark') => {
    
    
    if (theme === 'default') {
    
    
      window.less.modifyVars({
    
    
        '@primary-color': 'red !important',
        '@border-color-base': '#E9EEF7 !important',
        '@layout-body-background': '#f0f2f5 !important',
        '@layout-header-background': '#fffffe !important',
        '@component-background': '#fffffe !important',
        '@text-color': 'fade(@black, 65%) !important',
        '@title-color': '#333 !important',
        '@table-header-bg': 'hsv(0, 0, 98%) !important',
        '@ant-selected-color': 'rgba(0, 0, 0, 0.65) !important',
        '@table-row-hover-bg': '#F0FDFF !important',
        '@modal-heading-color': 'fade(#000, 85%) !important',
        '@page-ellipsis-color': 'rgba(0, 0, 0, 0.25) !important',
        '@empty-text-color': 'rgba(0, 0, 0, 0.25) !important',
        '@date-last-next': 'rgba(0, 0, 0, 0.25) !important',
        '@cursor-text-color': '#1f1f1f !important',
        '@descriptions-title-color': 'rgba(0, 0, 0, 0.85) !important',
        '@descriptions-label-bg-color': '#fafafa !important',
        '@alarm-chart-bg-color': '#f2f6fa !important',
        '@statistic-title-color': 'rgba(0, 0, 0, 0.45) !important',
        '@dashboard-box-shadow': '0 1px 4px rgba(0, 0, 0, 0.15) !important',
      });
    } else {
    
    
      window.less.modifyVars({
    
    
        '@primary-color': 'black !important',
        '@border-color-base': '#303030 !important',
        '@layout-body-background': '#000001 !important',
        '@layout-header-background': '#1f1f1f !important',
        '@component-background': '#141414 !important',
        '@text-color': 'rgba(255, 255, 255, 0.65) !important',
        '@title-color': 'rgba(255, 255, 255, 0.85) !important',
        '@table-header-bg': '#1d1d1d !important',
        '@ant-selected-color': '#1f1f1f !important',
        '@table-row-hover-bg': '#000001 !important',
        '@modal-heading-color': 'fade(@white, 100%) !important',
        '@page-ellipsis-color': 'rgba(255, 255, 255, 0.25) !important',
        '@empty-text-color': 'rgba(255, 255, 255, 0.45) !important',
        '@date-last-next': 'rgba(255, 255, 255, 0.25) !important',
        '@cursor-text-color': '#fefefe !important',
        '@descriptions-title-color': 'rgba(255, 255, 255, 0.85) !important',
        '@descriptions-label-bg-color': '#101010 !important',
        '@alarm-chart-bg-color': '#0d0905 !important',
        '@statistic-title-color': 'rgba(255, 255, 255, 0.45) !important',
        '@dashboard-box-shadow':
          '0 1px 4px rgba(255, 255, 255, 0.4) !important',
      });
    }
  };

  • 就是这玩意的优先级很低,全部得加important覆盖。要么需要去除antd自动引入的样式。

方案二

  • 使用css 变量替换
  • 利用umi-plugin-antd-theme
  • 由于我用的umi3,网上都是umi2的教程,踩了不少坑。
  • 因为umi文档上说会自动检测插件,那么我打印umi plugin list --key时看见antd-theme插件的key是antdTheme,结果尼玛在umirc里配这个键直接报错。
  • 后来看别人的发现就在config里建个theme.config.json即可:
{
    
    
  "theme": [
    {
    
    
      "key": "normal",
      "fileName": "normal.css",
       "modifyVars": {
    
       }
    },
    {
    
    
      "key": "dust",
      "fileName": "dust.css",
      "modifyVars": {
    
     "@primary-color": "#F5222D" }
    },
    {
    
    
      "key": "volcano",
      "fileName": "volcano.css",
      "modifyVars": {
    
     "@primary-color": "#FA541C" }
    },
    {
    
    
      "key": "sunset",
      "fileName": "sunset.css",
      "modifyVars": {
    
     "@primary-color": "#FAAD14" }
    },
    {
    
    
      "key": "cyan",
      "fileName": "cyan.css",
      "modifyVars": {
    
     "@primary-color": "#13C2C2" }
    },
    {
    
    
      "key": "green",
      "fileName": "green.css",
      "modifyVars": {
    
     "@primary-color": "#52C41A" }
    },
    {
    
    
      "key": "geekblue",
      "fileName": "geekblue.css",
      "modifyVars": {
    
     "@primary-color": "#2F54EB" }
    },
    {
    
    
      "key": "purple",
      "fileName": "purple.css",
      "modifyVars": {
    
     "@primary-color": "#722ED1" }
    },
    {
    
    
      "key": "dark",
      "fileName": "dark.css",
      "theme": "dark",
      "modifyVars": {
    
    
        "@table-selected-row-bg": "#30303d !important",
        "@menu-dark-bg": "#23232E",
        "@menu-dark-submenu-bg": "#23232E"
      }
    },
    {
    
    
      "key": "dust",
      "theme": "dark",
      "fileName": "dark-dust.css",
      "modifyVars": {
    
    
        "@primary-color": "#F5222D",
        "@table-selected-row-bg": "#30303d !important",
        "@menu-dark-bg": "#23232E",
        "@menu-dark-submenu-bg": "#23232E"
      }
    },
    {
    
    
      "key": "volcano",
      "theme": "dark",
      "fileName": "dark-volcano.css",
      "modifyVars": {
    
    
        "@primary-color": "#FA541C",
        "@table-selected-row-bg": "#30303d !important",
        "@menu-dark-bg": "#23232E",
        "@menu-dark-submenu-bg": "#23232E"
      }
    },
    {
    
    
      "key": "sunset",
      "theme": "dark",
      "fileName": "dark-sunset.css",
      "modifyVars": {
    
    
        "@primary-color": "#FAAD14",
        "@table-selected-row-bg": "#30303d !important",
        "@menu-dark-bg": "#23232E",
        "@menu-dark-submenu-bg": "#23232E"
      }
    },
    {
    
    
      "key": "cyan",
      "theme": "dark",
      "fileName": "dark-cyan.css",
      "modifyVars": {
    
    
        "@primary-color": "#13C2C2",
        "@table-selected-row-bg": "#30303d !important",
        "@menu-dark-bg": "#23232E",
        "@menu-dark-submenu-bg": "#23232E"
      }
    },
    {
    
    
      "key": "green",
      "theme": "dark",
      "fileName": "dark-green.css",
      "modifyVars": {
    
    
        "@primary-color": "#52C41A",
        "@table-selected-row-bg": "#30303d !important",
        "@menu-dark-bg": "#23232E",
        "@menu-dark-submenu-bg": "#23232E"
      }
    },
    {
    
    
      "key": "geekblue",
      "theme": "dark",
      "fileName": "dark-geekblue.css",
      "modifyVars": {
    
    
        "@primary-color": "#2F54EB",
        "@table-selected-row-bg": "#30303d !important",
        "@menu-dark-bg": "#23232E",
        "@menu-dark-submenu-bg": "#23232E"
      }
    },
    {
    
    
      "key": "purple",
      "theme": "dark",
      "fileName": "dark-purple.css",
      "modifyVars": {
    
    
        "@primary-color": "#722ED1",
        "@table-selected-row-bg": "#30303d !important",
        "@menu-dark-bg": "#23232E",
        "@menu-dark-submenu-bg": "#23232E"
      }
    }
  ],
  "min": true,
  "isModule": true,
  "ignoreAntd": false,
  "ignoreProLayout": false,
  "cache": true
}
  • 比如就切换浅色和暗黑,只要:
import cssVars from 'css-vars-ponyfill';

export type ThemeType = keyof typeof THEME;

export const THEME = {
    
    
  Light: {
    
    
    '--font-high-emphasis': 'rgba(1, 8, 30, 1)',
    '--font-primary': 'rgba(36, 174, 143, 1)',
  },
  Dark: {
    
    
    '--font-high-emphasis': 'rgba(255, 255, 255, 1)',
    '--font-primary': 'rgba(237, 110, 114, 1)',
  },
};

export const setTheme = (themeKey: ThemeType) => {
    
    
  const themeKeys = Object.keys(THEME);
  let KEY: ThemeType;
  if (themeKeys.includes(themeKey)) {
    
    
    KEY = themeKey;
  } else {
    
    
    KEY = (localStorage.getItem('theme') as ThemeType | undefined) || 'Light';
  }
  localStorage.setItem('theme', KEY);

  let styleLink = document.getElementById('theme-style') as HTMLLinkElement;
  let hrefSrc = '/theme/normal.css';
  if (KEY === 'Light') {
    
    
    hrefSrc = '/theme/normal.css';
  } else if (KEY === 'Dark') {
    
    
    hrefSrc = '/theme/dark.css';
  }

  if (styleLink) {
    
    
    styleLink.href = hrefSrc;
  } else {
    
    
    styleLink = document.createElement('link');
    styleLink.type = 'text/css';
    styleLink.rel = 'stylesheet';
    styleLink.id = 'theme-style';
    styleLink.href = hrefSrc;
    document.body.append(styleLink);
  }
  cssVars({
    
    
    onlyLegacy: false,
    variables: THEME[KEY],
    onError() {
    
    
      cssVars({
    
    
        onlyLegacy: false,
        variables: THEME[KEY],
      });
    },
  });
};

  • js中进行切换即可:
  const setThemeColor = (theme: 'default' | 'dark') => {
    
    
    if (theme === 'default') {
    
    
      setTheme('Light');
    } else {
    
    
      setTheme('Dark');
    }
  };
  • 部分变量会提示没有,请自己注入进去。
  • 另外 “modifyVars” 不填或者填个空会导致antd-pro-merge-less插件报错或者在更新时,但不影响编译结果。

猜你喜欢

转载自blog.csdn.net/yehuozhili/article/details/116587089