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
antd在線換膚定制功能