React+antd在線上動態更換皮膚主題


原理:

但官方提供的這種方式只能在編譯時改變主題,無法在運行性動態切換。下面就是本文的重點,如何實現在運行時動態切換主題。

提取antd的less變量文件
我們的思路就是提取ant-design-vue中所有的less代碼匯總到一個文件中,然后在index.html頁面中直接引用,最后使用less.js中的modifyVars方法修改主題變量,這樣antd的樣式就不會被編譯,實現運行時動態切換

1.首先安裝提取less文件的插件antd-theme-webpack-plugin

2.在variables.less文件中添加主題變量(一定要與options中的themeVariables一致!)

3.index.less可以為空

4.使用window.less.modifyVars()方法修改主題

5.需要將less的版本號改成3.0以下,否則后面再更改主題時會出錯!!!這里改成了2.7.2

 

開始
因為項目里一個更換皮膚的功能,雖然antd官網給出了更改主題的方法,但那是靜態的,沒辦法在線上更換,然后發現網上在這方面的資料也並不多,這個業務難道不是應該很普遍嗎?然后我就花了一些時間去解決了這個問題,並將踩過的坑寫出來,再給出解決方案。

antd-theme-webpack-plugin
這個工具是我在網上找到的。下面是這個包的文檔,但這個文檔實際上寫的並不清楚,我在按文檔寫的過程里遇到了很多的坑。

antd-theme-webpack-plugin文檔

我們先在控制台執行:
yarn run antd-theme-webpack-plugin -D

然后去webpack.config.common.js里配置:

//頂部引入
const AntDesignThemePlugin = require('antd-theme-webpack-plugin');

//需要在less-loader里配置options,這個配置是在less的配置規則下
{
loader:'less-loader',
options:{
//這里需要在less的配置規則里打開javascriptEnabled
javascriptEnabled: true,
}
}


//在plugins里
plugins:[
new AntDesignThemePlugin({
antDir: path.join(__dirname, './node_modules/antd'),//antd包位置
stylesDir: path.join(__dirname, './src/styles/theme'),//指定皮膚文件夾
varFile: path.join(__dirname, './src/styles/theme/variables.less'),//自己設置默認的主題色
indexFileName: './public/index.html',
mainLessFile: path.join(__dirname, './src/styles/theme/index.less'),
outputFilePath: path.join(__dirname, './dist/theme/color.less'),//輸出到什么地方
themeVariables: [//這里寫要改變的主題變量
'@primary-color',
'@btn-primary-bg',
],
generateOnce:false
})
]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
這里的配置有幾個坑點,等下結合后面一起說。

然后我們去index.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>React</title>
</head>
<body>
<link rel="stylesheet/less" type="text/css" href="./theme/color.less" /><!--這里link放在哪,style生成在哪里,注意樣式被覆蓋-->
<script>
window.less = {
async: false,
env: 'production'//production development
};
</script>
<div id="root"></div>
<script src="https://cdn.bootcss.com/less.js/2.7.3/less.min.js">
</script>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
html這里有幾個坑:
1.注意link標簽放的位置,要放在body的第一行里,因為到時候style是會生成在該ling標簽下面的,如果你把link放在head里,到時候生成的主題樣式會被覆蓋掉。
2. 我們需要在這里引入less文件,因為我們需要使用到window.less這個對象里的方法,但是我們不能引入less3.0以上的,不然瀏覽器控制台會報下面這樣的錯,樣式也不會出現。


然后在styles的文件夾下創建文件,這里文件創建的路徑需要和webpack.config.common.js里寫的路徑一樣。


然后在variables.less里:

//在頂部加上這一行
@import "~antd/lib/style/themes/default.less";

@primary-color: #6064f4;
@btn-primary-bg: #ccc849;
1
2
3
4
5
然后把要更換的主題顏色給寫上去,把antd默認的主題顏色給覆蓋掉,這里有個坑的地方是,這里的兩個顏色變量一定要寫上去,不然有的時候會出現更換主題顏色失敗的情況。

index.less這個文件其實是可有可無的,我們可以不在里面寫東西,但是我在項目里用到了,后面會說。

然后我們去頁面里寫一下:

handleClick(){
window.less.modifyVars(//更換主題顏色要這么寫
{
'@primary-color': '#e64e14',
'@btn-primary-bg': '#5d72cc',
}
)
.then(() => {console.log('success')})
.catch(error => {
console.log(error);
});
}
render() {
return (
<div className='minor-borderTop major-fontColor'>
<Button onClick={this.handleClick} type={'primary'}>更換</Button>
</div>
)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
然后坑的地方來了,如果你想要使用variable.less里的變量,一般來說我們都是在自己新建的less文件的頂部引入這個文件,然后在用到顏色的地方直接加上@primary-color這個變量,但是這里不行,因為它只會把variables.less和index.less這兩個文件里的變量給更改了,其他的文件是固定生成的,不會被覆蓋。所以如果你想用得反過來,比如在新建的less文件里使用變量,然后在variables.less的頂部引入。但這樣肯定是不好的,react有那么多組件,如果每個都引入到這個variabkes.less的頂部的話,那得多大?

然后我想了兩個辦法,

使用css的變量var,在variabkes.less文件里,像下面這樣寫:
@primary-color: #6064f4;
@btn-primary-bg: #ccc849;

:root{
--primary:@primary-color;
}
1
2
3
4
5
6
這樣子你需要使用的less文件里就可以引入variabkes.less文件,然后這樣寫background:var(--primary),這樣在@primary-color改變了之后,–primary也可以拿到了。但是這個方法有兼容性問題,ie完全不支持css變量,所以這個方法適合不需要兼容ie的使用。

這里就用到了我之前說的index.less,我們在index.less的頂部引入variabkes.less,在里面寫:
.primary-bg{
background-color:@primary-color;
}

.fontColor{
color:@primary-8;
}
1
2
3
4
5
6
7
我們可以直接新建幾個類,寫上背景顏色,文字顏色,等@primary-color改變的時候,類里的顏色也會發生改變。然后在需要的地方引用這個index.less,然后去組件里加上這個類就行了。其實這個方法算是稍微有點low,但是這個也算是一個比較好的解決辦法,因為你要加的類其實沒有幾個,背景顏色類,字體顏色類。這里講一下你要改變的顏色變量必須要是antd定義好的,你自己定義一個比如@primary-fontColor是沒用的,因為antd並沒有這個變量,如果你要看antd定義了哪些變量,可以去node_modules/antd/lib/style/themes/default.less這個文件里看。上面那里我使用的@primary-8這個變量就是antd自己定義的,這個變量是根據@primary-color的顏色來變化的,所以我們不需要在webpack引入,數字越大顏色越深。

然后開始打包,你需要在dist文件夾下創建一個theme文件夾,然后才能去執行打包命令,然后你會發現,在theme文件夾下有一個color.less文件,在根目錄下也有一個color.less文件,你可以把根目錄下的color.less刪除,這個是多余生成的。

然后我們打開自己寫的頁面:

可以發現主題顏色是我們在variables.less定義的默認顏色,然后我們點擊按鈕,頁面變成了下面這樣:

變成了我們在按鈕點擊事件里定義的顏色了。

我們發現link下面生成了一個style文件,這里就是之前說的顏色注意被覆蓋的問題了。

如果你想要更多的顏色,可以引入調色盤的組件去改變主題顏色,比如antd官網拉到最下方可以改變主題顏色那樣。

結尾
這章寫了很多東西,主要是有坑的地方太多了,我寫的又比較詳細,但同時感覺也寫的有點復雜了,如果又不懂的可以在評論里問。
————————————————
版權聲明:本文為CSDN博主「web999_Z」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/asdqwe_zxc/java/article/details/88309987


免責聲明!

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



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