使用React+Umi+Ant Design Pro实现生产环境动态切换主题,支持暗黑主题

Posted dygood

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用React+Umi+Ant Design Pro实现生产环境动态切换主题,支持暗黑主题相关的知识,希望对你有一定的参考价值。

  投入前端开发也有1年的时间了,我还是很菜.在开发中还是很多技巧以及经验不够,写文章也是文笔不行,不过好在写的内容意思大概都能看懂.这次就来介绍一下我在开发过程中遇到的一些问题以及处理技巧.

  两月前刚开始试用umi这个React的框架,使用AntD Pro创建好项目后,着实熟悉了几天,不过熟悉这个框架后,就觉得阿里的大佬还是牛.佩服.

  事情是这样的,我们能够在AndD Pro的在线预览上看到能够动态切换主题.而实际拉下来的模板中却没有这个功能.我就开始了对比源码.

  算了,先上一下项目目录结构吧,不然说起来不知所云.被我精简后的项目结构大概就是这样.删掉了,很多用于语法验证的ESLINT库等,使用VS插件提供支持,这么做的好处就是写代码的时候就能进行验证,格式化,而不是编译和提交的时候去搞这一堆事情.

  技术图片

 

回到主题,我发现源码中的layouts中的BasicLayout中缺少了,SettingDrawer的引用.所以这里我们自己把他加上,并放在页面中

技术图片技术图片

 

在model中的setting中使用默认的切换主题的代码就能实现动态切换主题了.

以为到这里就完了?

嘿嘿,其实并没有.

你会发现这个东西,不管你怎么切换主题,界面是没有反应的,只有默认主题,这.....心里肯定是崩溃的.

所以我们还需要做一些处理.

首先按照官方的默认主题配置中写好想要的默认主题.就是这个default.config文件.名字可能和官方不太一样,因为我自己这个项目我改了很多文件名的.

技术图片

 

这个文件的作用就是告诉umi框架默认主题就是这个样的,

然后我们去命令行工具添加几个好东西.

首先我们先添加

umi-plugin-antd-theme
这个插件.对,没错,就这一个好东西??可以使用npm命令,或者yarn命令进行添加.从名字我们可以发现这个库是umi的一个插件.
所以接下来就是配置这个插件.通过antd官方的例子我们可以看到支持的主题整成了一个单独的主题样式文件.
在我这里就是theme.config文件.
我这里贴一下官方案例中文件的内容
export const themeConfig = {
  theme: [
    { key: ‘dark‘, fileName: ‘dark.css‘, theme: ‘dark‘ },
    { 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: ‘dust‘, theme: ‘dark‘, fileName: ‘dark-dust.css‘, modifyVars: { ‘@primary-color‘: ‘#F5222D‘ } },
    { key: ‘volcano‘, theme: ‘dark‘, fileName: ‘dark-volcano.css‘, modifyVars: { ‘@primary-color‘: ‘#FA541C‘ } },
    { key: ‘sunset‘, theme: ‘dark‘, fileName: ‘dark-sunset.css‘, modifyVars: { ‘@primary-color‘: ‘#FAAD14‘ } },
    { key: ‘cyan‘, theme: ‘dark‘, fileName: ‘dark-cyan.css‘, modifyVars: { ‘@primary-color‘: ‘#13C2C2‘ } },
    { key: ‘green‘, theme: ‘dark‘, fileName: ‘dark-green.css‘, modifyVars: { ‘@primary-color‘: ‘#52C41A‘ } },
    { key: ‘geekblue‘, theme: ‘dark‘, fileName: ‘dark-geekblue.css‘, modifyVars: { ‘@primary-color‘: ‘#2F54EB‘ } },
    { key: ‘purple‘, theme: ‘dark‘, fileName: ‘dark-purple.css‘, modifyVars: { ‘@primary-color‘: ‘#722ED1‘ } }
  ],
  min: true, // 是否压缩css
  isModule: true, // css module
  ignoreAntd: false, // 忽略 antd 的依赖
  ignoreProLayout: false, // 忽略 pro-layout
  cache: true // 不使用缓存
};

 

写好这个文件后,就可以在config中配置主题了.接下来我直接贴图.

技术图片

 

 

 

特别注意的地方就是这几个箭头处,首先导入主题文件,然后配置umi插件使用主题配置,然后特别注意的就是不再配置umi默认的那个webpack的主题了,给他一个空对象就行了.
然后我们编译项目,发布后,在线浏览项目,发现主题已经可以正常切换了.这里再次膜拜一下大佬们的贡献.
 
然鹅......我们点一下浏览器的刷新按钮就会发现,主题又恢复默认了. ??简直是....................
 
所以接下来我们就得研究一下为什么主题又变成了默认.
 
首先我们就看到SettingDrawer这个组件调用的方法,setting/changeSetting 所以我们就去model中的setting文件看看是什么原因,发现,这个地方无论你怎么改主题,取得主题都是默认配置.
原来是读取的总是默认配置,这下就知道为啥了.所以我们对这个model进行一下改造直接贴出我的代码.
import { defaultConfig } from ‘../../config/default.config‘;

const updateColorWeak = colorWeak => {
  const root = document.getElementById(‘root‘);
  if (root) {
    root.className = colorWeak ? ‘colorWeak‘ : ‘‘;
  }
};

const themeData = JSON.parse(localStorage.getItem(‘smart-theme‘));

const SettingModel = {
  namespace: ‘settings‘,
  state: themeData || defaultConfig,
  reducers: {
    changeSetting(state = defaultConfig, { payload }) {
      const { colorWeak, contentWidth } = payload;
      if (state.contentWidth !== contentWidth && window.dispatchEvent) {
        window.dispatchEvent(new Event(‘resize‘));
      }
      updateColorWeak(!!colorWeak);
      localStorage.setItem(‘smart-theme‘, JSON.stringify({ ...state, ...payload }));
      return { ...state, ...payload };
    }
  }
};
export default SettingModel;

我的改动实际上就是如图的三个地方,首先在修改后返回样式之前将样式存到localStorage,由于他是个对象,所以需要转成字符串.然后再取出来并且转成字符串,以后在每一次state返回的时候,默认返回localStrage中的配置信息,若是不存在就返回默认的.

技术图片

 

 

到这里我们就能愉快的进行在生产环境切换主题了.

 ヾ(≧▽≦*)oヾ(≧▽≦*)oヾ(≧▽≦*)o 至此,我们的在线主题切换就全部完成了,结合官方默认的主题就能支持暗黑模式了.

然鹅......你以为完了???其实还没有,因为还有一个问题.官方的默认暗黑主题,表格被选中后的背景色还是白色.那么你在黑色的主题下,用白色的背景,效果就是下面这样

 

 技术图片

 

 显示效果是不是很棒,完全不知道数据是什么.而且亮瞎眼.??

所以我们还需要对官方提供的主题配置做点手脚.

那就是在所有的黑色主题的配置中加入自定义的配置 

‘@table-selected-row-bg‘: ‘#30303d !important‘
用来修改默认的选中后的背景色.这里加一个!important表示强制使用.
接下来我贴一下我的theme.config文件的内容.
export const themeConfig = {
  theme: [
    { 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‘ } },
    { key: ‘dust‘, theme: ‘dark‘, fileName: ‘dark-dust.css‘, modifyVars: { ‘@primary-color‘: ‘#F5222D‘, ‘@table-selected-row-bg‘: ‘#30303d !important‘ } },
    { key: ‘volcano‘, theme: ‘dark‘, fileName: ‘dark-volcano.css‘, modifyVars: { ‘@primary-color‘: ‘#FA541C‘, ‘@table-selected-row-bg‘: ‘#30303d !important‘ } },
    { key: ‘sunset‘, theme: ‘dark‘, fileName: ‘dark-sunset.css‘, modifyVars: { ‘@primary-color‘: ‘#FAAD14‘, ‘@table-selected-row-bg‘: ‘#30303d !important‘ } },
    { key: ‘cyan‘, theme: ‘dark‘, fileName: ‘dark-cyan.css‘, modifyVars: { ‘@primary-color‘: ‘#13C2C2‘, ‘@table-selected-row-bg‘: ‘#30303d !important‘ } },
    { key: ‘green‘, theme: ‘dark‘, fileName: ‘dark-green.css‘, modifyVars: { ‘@primary-color‘: ‘#52C41A‘, ‘@table-selected-row-bg‘: ‘#30303d !important‘ } },
    { key: ‘geekblue‘, theme: ‘dark‘, fileName: ‘dark-geekblue.css‘, modifyVars: { ‘@primary-color‘: ‘#2F54EB‘, ‘@table-selected-row-bg‘: ‘#30303d !important‘ } },
    { key: ‘purple‘, theme: ‘dark‘, fileName: ‘dark-purple.css‘, modifyVars: { ‘@primary-color‘: ‘#722ED1‘, ‘@table-selected-row-bg‘: ‘#30303d !important‘ } }
  ],
  min: true, // 是否压缩css
  isModule: true, // css module
  ignoreAntd: false, // 忽略 antd 的依赖
  ignoreProLayout: false, // 忽略 pro-layout
  cache: true // 不使用缓存
};

经过以上的一系列步骤和调整,终于能过够正常的在线切换主题,并且刷新也不会造成恢复默认了.

接下来是一个效果图.

 

 技术图片

以上是关于使用React+Umi+Ant Design Pro实现生产环境动态切换主题,支持暗黑主题的主要内容,如果未能解决你的问题,请参考以下文章

手把手教你创建Ant Design Pro的React项目

Ant Design Pro umi-request credentials: include 跨域问题

umi改为路由改为hash模式,Ant Design Pro Components的ProLayout 菜单不出来了

ant-design-pro 开发 基于react 框架涉及到技术你的本地环境需要安装 yarnnode 和 git。我们的技术栈基于 ES2015+ReactUmiJSdvag2 和 a

如何创建Pull Request,以开源项目ant design pro为例

移除antd pro中的 路由的国际化