使用React+Umi+Ant Design Pro實現生產環境動態切換主題,支持暗黑主題


  目前新版的Antd4.x,Umi3.x,Antd Pro V5預覽版均已經可以正常使用.建議升級到最新版使用最新的特性.如下為新版本使用動態主題的鏈接.https://www.cnblogs.com/dygood/p/13026318.html  

 

  投入前端開發也有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文件的內容.
 1 const darkThemePublicStyles = {
 2   '@table-selected-row-bg': '#30303d !important',
 3   '@menu-dark-bg': '#23232E',
 4   '@menu-dark-submenu-bg': '#23232E'
 5 };
 6 
 7 export const themeConfig = {
 8   theme: [
 9     { key: 'dust', fileName: 'dust.css', modifyVars: { '@primary-color': '#F5222D' } },
10     { key: 'volcano', fileName: 'volcano.css', modifyVars: { '@primary-color': '#FA541C' } },
11     { key: 'sunset', fileName: 'sunset.css', modifyVars: { '@primary-color': '#FAAD14' } },
12     { key: 'cyan', fileName: 'cyan.css', modifyVars: { '@primary-color': '#13C2C2' } },
13     { key: 'green', fileName: 'green.css', modifyVars: { '@primary-color': '#52C41A' } },
14     { key: 'geekblue', fileName: 'geekblue.css', modifyVars: { '@primary-color': '#2F54EB' } },
15     { key: 'purple', fileName: 'purple.css', modifyVars: { '@primary-color': '#722ED1' } },
16     { key: 'dark', fileName: 'dark.css', theme: 'dark', modifyVars: darkThemePublicStyles },
17     { key: 'dust', theme: 'dark', fileName: 'dark-dust.css', modifyVars: { '@primary-color': '#F5222D', ...darkThemePublicStyles } },
18     { key: 'volcano', theme: 'dark', fileName: 'dark-volcano.css', modifyVars: { '@primary-color': '#FA541C', ...darkThemePublicStyles } },
19     { key: 'sunset', theme: 'dark', fileName: 'dark-sunset.css', modifyVars: { '@primary-color': '#FAAD14', ...darkThemePublicStyles } },
20     { key: 'cyan', theme: 'dark', fileName: 'dark-cyan.css', modifyVars: { '@primary-color': '#13C2C2', ...darkThemePublicStyles } },
21     { key: 'green', theme: 'dark', fileName: 'dark-green.css', modifyVars: { '@primary-color': '#52C41A', ...darkThemePublicStyles } },
22     { key: 'geekblue', theme: 'dark', fileName: 'dark-geekblue.css', modifyVars: { '@primary-color': '#2F54EB', ...darkThemePublicStyles } },
23     { key: 'purple', theme: 'dark', fileName: 'dark-purple.css', modifyVars: { '@primary-color': '#722ED1', ...darkThemePublicStyles } }
24   ],
25   min: true, // 是否壓縮css
26   isModule: true, // css module
27   ignoreAntd: false, // 忽略 antd 的依賴
28   ignoreProLayout: false, // 忽略 pro-layout
29   cache: true // 不使用緩存
30 };

 

經過以上的一系列步驟和調整,終於能過夠正常的在線切換主題,並且刷新也不會造成恢復默認了.

接下來是一個效果圖.

 

 

哦,對了,還要注意一下插件的版本,最新的那個theme插件更新后有問題.我還沒測試新版的.這里我說一下我使用的版本號.
"umi-plugin-antd-theme": "^1.0.15",
"umi": "^2.13.5",
"antd": "^3.26.13",
"@ant-design/pro-layout": "^4.11.3",
我是在這個版本的基礎上實現的,你用了最新的版本可能就不一樣了.

同樣,官方antD 4.x支持暗黑主題了.所以建議大家嘗試使用新版的庫.

等到官方模板項目更新了Umi 3.x后,我再進行升級測試.到時候可能實現方式不太一樣.測試OK后,我會重新寫一篇.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM