1. 程式人生 > >antd線上換膚定製功能

antd線上換膚定製功能

最近react專案,用的antd框架,然後看見他的antdPro例子裡面有個定製功能很帥,老大說做,那就做吧,鼓搗了一晚終於實現了。

css換膚

入行前端的時候經常看魚哥(張鑫旭)的部落格,記得看過 這篇 ,當時很驚歎,原理其實很簡單,就是我們最能想到的方式,多個css,然後用JS替換從而達到換膚效果。但是這個有侷限性,比如我們用的是antdUI庫,我們不可能每個顏色都去搞個css吧。當時現在我們有less,sass,而且原生的css也有變數var了,所以新時代我們有新技術達到這個效果。

less換膚

其實antd官網是有 定製主題 的,但是是靜態的,通過打包之前去設定一些config,less變數從而達到定製效果,但是這顯然不是我們想要的==線上實時==換膚效果。

最初我的思路是用node去實時生成一個webpack.config.base的配置檔案,但是這樣只能在開發環境實現換膚,生成環境是沒辦法的。然後網上有人說,用less去生成多個css檔案,這不又走了以前的老路嗎。最後沒辦法我把antdPro的原始碼拿來看了下,終於找到了解決辦法,antd-theme-generator

步驟

  • 這裡我的專案是在自己寫的 webpack4-react腳手架 的基礎上做修改的,如果你用的create-react-app或者其他的腳手架可能會有相應修改。
  • 安裝cnpm i antd-theme-generator --save
  • index.html
<body
>
<link rel="stylesheet/less" type="text/css" href="static/color.less" /> //主要是這個起作用 <script> window.less = { async: false, env: 'production' }; </script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js"
>
</script> <noscript> You need to enable JavaScript to run this app. </noscript> <div id="root"></div> </body>
  • 根目錄新增color.js
const path = require('path');
const { generateTheme, getLessVars } = 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/vars.less'), //對應具體位置
  mainLessFile: path.join(__dirname, './src/styles/main.less'), //對應具體位置
  themeVariables: [
    '@primary-color',
    '@secondary-color',
    '@text-color',
    '@text-color-secondary',
    '@heading-color',
    '@layout-body-background',
    '@btn-primary-bg',
    '@layout-header-background'
  ],
  indexFileName: 'index.html',
  outputFilePath: path.join(__dirname, './src/static/color.less'),
}

generateTheme(options).then(less => {
  console.log('Theme generated successfully');
})
  .catch(error => {
    console.log('Error', error);
  });
  • src新增styles資料夾,裡面有vars.less和main.less
//vars.less
@import "~antd/lib/style/themes/default.less";
@link-color: #00375B;
@primary-color: #00375B;
:root { 
    --PC: @primary-color;   //color.less中加入css原生變數:--PC
 }

//main.less
//可為空,只是為了不報錯才引入
  • package.json
//為了每次自動node color.js,所以scripts裡面修改下
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "node color &&  webpack-dev-server --config webpack.config.dev.js", 
    "start": "npm run dev",
    "build": "node color && webpack --config webpack.config.prod.js"
  },
  • 使用,啟動後直接window.less.modifyVars就可以了
window.less
    .modifyVars(
        {
            '@primary-color': '#ee5e7b',
            '@link-color': '#ee5e7b',
            '@btn-primary-bg': 'ee5e7b',
        }
    )
    .then(() => { })
    .catch(error => {
        message.error(`Failed to update theme`);
    });
  • 最後,打包後注意放入環境後開啟,否則會報錯。

原理

我們發現其實他生效主要就是靠color生成一個color.less檔案,然後我開啟color.less檔案看了下,發現原來是利用的less可以寫邏輯這個特性實現的,從而通過window.less.modifyVars去動態的改變less變數。

其他

現在antd的換膚問題解決了,但是我們自己的css樣式怎麼辦呢,比如我有個標題想用主題色,我怎麼去拿到這個顏色呢。
+ 起初我是這樣實現的vars.less增加

//vars.less
 .primary-color{
     color:@primary-color
 }

這樣.primary-color就會打入生成的color.less裡面,然後我們就可以用了,當時這樣有些地方就不方便,比如box-shadow: 1px 1px 1px 1px #d23333;,我們怎麼辦,難道每次都要寫在vars.less裡面嗎
+ 所以這裡我用了css的原生變數var

//vars.less
:root { 
    --PC: @primary-color;
 }

然後就可以使用box-shadow: 1px 1px 1px 1px var(--PC);

本地儲存

使用者設定顏色後,可以用快取或者localStorage儲存,這就不多說了

預覽效果

原始碼

最後

大家好,這裡是「 TaoLand 」,這個部落格主要用於記錄一個菜鳥程式猿的Growth之路。這也是自己第一次做部落格,希望和大家多多交流,一起成長!文章將會在下列地址同步更新……
個人部落格:www.yangyuetao.cn
小程式:TaoLand