vue+webpack 更換主題N種方案優(yōu)劣分析
需求:由于業(yè)務(wù)需要,我們需要做多套皮膚
調(diào)研了下當(dāng)前行業(yè)的實(shí)現(xiàn)方案,五花八門良莠不齊,在此總結(jié)下各種方案有優(yōu)劣及復(fù)雜度,供大家快速定位到符合自己業(yè)務(wù)的方案,以vue 單頁(yè)應(yīng)用為業(yè)務(wù)場(chǎng)景
方式一:class切換方式
實(shí)現(xiàn):
在每個(gè)需要更換的頁(yè)面定義多個(gè)class,根據(jù)運(yùn)行時(shí)標(biāo)識(shí)動(dòng)態(tài)的切換class名稱實(shí)現(xiàn)加載不同的樣式,這種方式較為簡(jiǎn)單
優(yōu)點(diǎn):
- 不需要修改構(gòu)建工具相關(guān)
- 業(yè)務(wù)開(kāi)發(fā)過(guò)程可以實(shí)現(xiàn),沒(méi)有限制
- 支持動(dòng)態(tài)切換
缺點(diǎn):
- 邏輯分散耦合在各個(gè)頁(yè)面,一旦需要修改,涉及修改的頁(yè)面較多
- 代碼需要預(yù)先內(nèi)置,不支持動(dòng)態(tài)顏色修改
方式二:ElementUI的實(shí)現(xiàn)
實(shí)現(xiàn):
對(duì)主題涉及的顏色使用特殊值
如:UI需要白色#ffffff色值的時(shí)候使用一個(gè)相近的特征值顏色 如:#fffffe
// 將默認(rèn)樣式特征值替換為變量,用于多次替換
getStyleTemplate(data) {
const colorMap = {
'#fffffe': 'text_color'
};
Object.keys(colorMap).forEach(key => {
const value = colorMap[key];
data = data.replace(new RegExp(key, 'ig'), value);
});
return data;
},
在代碼運(yùn)行時(shí)動(dòng)態(tài)獲取到需要修改的顏色值
如: 需要修改#fffffe =》 #ff00ff
// 通過(guò)用戶操作或者接口,獲取到要替換的色值
colors:{
text_color: '#ff00ff'
}
查找頁(yè)面所有style標(biāo)簽將其色值#fffffe正則匹配出來(lái),替換為 #ff00ff
// 獲取默認(rèn)樣式,可以從已加載的 style 中獲取也可以從 css link 獲取
getIndexStyle() {
document.querySelectorAll('style').forEach(item=>{
this.originalStyle += this.getStyleTemplate(item.textContent);
})
},
getCssLink(){
this.get('./cssPath.css').then(json=>{
this.originalStyle = this.getStyleTemplate(json.data);
})
}
在頁(yè)面新加標(biāo)簽style覆蓋默認(rèn)值
// 替換默認(rèn)樣式表,插入 style 標(biāo)簽覆蓋樣式
writeNewStyle() {
let cssText = this.originalStyle;
log(cssText)
Object.keys(this.colors).forEach(key => {
cssText = cssText.replace(new RegExp('(:|\\s+)' + key, 'g'), '$1' + this.colors[key]);
});
cssText = cssText.replace(/\n/g,'')
if (this.originalStylesheetCount === document.styleSheets.length) {
const style = document.createElement('style');
style.innerText = cssText;
document.head.appendChild(style);
} else {
document.head.lastChild.innerText = cssText;
}
},
優(yōu)點(diǎn):
- 支持動(dòng)態(tài)切換
- 支持動(dòng)態(tài)色值
- 不需要內(nèi)置多份樣式
缺點(diǎn):
- 業(yè)務(wù)開(kāi)發(fā)過(guò)程中需要對(duì)ui給出的色值重定義,業(yè)務(wù)開(kāi)發(fā)需要有一定的規(guī)則
- 無(wú)法修改背景圖片
- 無(wú)法對(duì)懶加載的樣式做處理,需要初始化加載全局所有樣式
const ExtractTextPlugin = require('extract-text-webpack-plugin')
// 抽離css
module: {
loaders: [
{//抽離css 通過(guò)link加載
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
}
...
plugins: [
new ExtractTextPlugin({
filename: 'css/[name].css'
allChunks: true // 打包所有頁(yè)面css到同一個(gè)css 文件
})
]
- 無(wú)法動(dòng)態(tài)修改背景圖片
方式三:編譯時(shí)多主題全量構(gòu)建
實(shí)現(xiàn):
- 定義多套樣式
- 構(gòu)建時(shí)將多套樣式主題作為獨(dú)立構(gòu)建入口,構(gòu)建出主題靜態(tài)文件css文件
- 業(yè)務(wù)運(yùn)行時(shí)動(dòng)態(tài)加載不同的主題文件
優(yōu)點(diǎn):
- 支持動(dòng)態(tài)切換主題
- 業(yè)務(wù)開(kāi)發(fā)樣式分離
- 編譯時(shí)構(gòu)建性能較好 缺點(diǎn):
- 構(gòu)建工具配置較為復(fù)雜,適用單入口應(yīng)用,對(duì)多入口的支持不友好
- 需要定義全局 less 文件,在入口引入
- 業(yè)務(wù)需要額外操作
配合 rel="alternate stylesheet" 可預(yù)加載備選主題樣式
方式四: 編譯時(shí)選擇性構(gòu)建
實(shí)現(xiàn):
- 內(nèi)置多套皮膚
- 構(gòu)建時(shí)傳入?yún)?shù),根據(jù)不同的構(gòu)建參數(shù)加載不同的主題樣式文件
優(yōu)點(diǎn):
- 構(gòu)建工具配置較為簡(jiǎn)單,不需要業(yè)務(wù)做額外操作
- 多入口應(yīng)用支持度好
缺點(diǎn):
- 不支持動(dòng)態(tài)切換
- 多個(gè)項(xiàng)目需要構(gòu)建多次,需要構(gòu)建系統(tǒng)支持
方式五:less動(dòng)態(tài)變量
實(shí)現(xiàn):
- 修改構(gòu)建腳本,將所有頁(yè)面less文件抽到同一個(gè)文件中
- 不編譯less,頁(yè)面直接加載less文件
- 使用less.js 在客戶端編譯less 文件
less: {
modifyVars: {},
javascriptEnabled: true
}
優(yōu)點(diǎn):
- 支持動(dòng)態(tài)切換
- 支持動(dòng)態(tài)色值
缺點(diǎn):
- 客戶端編譯較耗性能/耗時(shí)
- 需要額外加載less.js mini文件size: 131KB
方式六:css變量
實(shí)現(xiàn):
在需要變化的css屬性定義變量
:root {
--main-bg-color: pink;
}
body {
background-color: var(--main-bg-color);
}
在運(yùn)行時(shí)動(dòng)態(tài)的修改變量
document.body.style.setProperty('--primary', '#7F583F');
優(yōu)點(diǎn):
- 瀏覽器原生支持,無(wú)需額外操作
- 支持動(dòng)態(tài)色值
缺點(diǎn):
- 低版本兼容性不好
ios Safari 9.3、 android 5、 chrome forAndroid 76
UC、QQ、Baidu 等國(guó)內(nèi)瀏覽器支持度較差
方式七: import動(dòng)態(tài)加載
實(shí)現(xiàn):
- 業(yè)務(wù)中預(yù)定義多套主題
- 運(yùn)行時(shí)根據(jù)變量動(dòng)態(tài)加載對(duì)應(yīng)主題
if(a){
import('./thems/a/base.less')
}else if(b){
import('./thems/b/base.less')
}
優(yōu)點(diǎn):
- 支持動(dòng)態(tài)切換
- 實(shí)現(xiàn)簡(jiǎn)單
缺點(diǎn):
- 不支持動(dòng)態(tài)色值
- 需要全局定義多套樣式表
- 全局定義 class 無(wú)法定義變量在 vue style 中引用變量
| 方式 | 動(dòng)態(tài)切換 | 動(dòng)態(tài)色值 | 支持變量 | 實(shí)現(xiàn)復(fù)雜度 | 兼容性 | 性能 | 維護(hù)性 |
|---|---|---|---|---|---|---|---|
| class切換方式 | 是 | 否 | 是 | 簡(jiǎn)單 | 良好 | 良好 | |
| ElementUI的實(shí)現(xiàn) | 是 | 是 | 是 | 中等 | 良好 | 一般 | |
| 編譯時(shí)多主題全量構(gòu)建 | 是 | 否 | 是 | 復(fù)雜 | 良好 | 一般 | |
| 編譯時(shí)選擇性構(gòu)建 | 否 | 否 | 是 | 中等 | 良好 | 良好 | |
| less變量 | 是 | 是 | 否 | 復(fù)雜 | 良好 | 差 | |
| css變量 | 是 | 是 | 是 | 中等 | 差 | 良好 | |
| import動(dòng)態(tài)加載 | 是 | 否 | 否 | 簡(jiǎn)單 | 良好 | 良好 |
注:
- 動(dòng)態(tài)切換:是否支持在運(yùn)行時(shí)切換皮膚
- 動(dòng)態(tài)設(shè)置:是否支持在運(yùn)行時(shí)動(dòng)態(tài)設(shè)置皮膚顏色
- 支持變量:是否可以再全局定義變量 less 文件,然后在不同的頁(yè)面引用 less,依賴其中的變量,還是需要在全局 less 文件里面定義全局 class
- 實(shí)現(xiàn)復(fù)雜度: 需要修改的代碼量包括構(gòu)建工具和業(yè)務(wù)代碼
- 兼容性: 主流瀏覽器支持程度
- 性能:包括代碼的首屏加載的 size、切換的速度、切換的時(shí)候會(huì)不會(huì)有閃動(dòng)
參考資料:
https://panjiachen.github.io/vue-element-admin-site/zh/guide/advanced/theme.html#樣式覆蓋
https://developer.mozilla.org/zh-CN/docs/Web/CSS/Alternative_style_sheets
https://less.bootcss.com
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Vue3中關(guān)于ref和reactive的問(wèn)題
這篇文章主要介紹了Vue3中關(guān)于ref和reactive的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
effect返回runner單測(cè)實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了effect返回runner單測(cè)實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Vue Echarts渲染數(shù)據(jù)導(dǎo)致殘留臟數(shù)據(jù)的問(wèn)題處理
這篇文章主要介紹了Vue Echarts渲染數(shù)據(jù)導(dǎo)致殘留臟數(shù)據(jù)的問(wèn)題處理,文中通過(guò)代碼示例給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-08-08
解決vue3項(xiàng)目中el-menu不兼容SSR問(wèn)題
這篇文章主要介紹了解決vue3項(xiàng)目中el-menu不兼容SSR問(wèn)題,需要的朋友可以參考下2023-12-12
使用element-ui,el-row中的el-col數(shù)據(jù)為空頁(yè)面布局變亂問(wèn)題
這篇文章主要介紹了使用element-ui,el-row中的el-col數(shù)據(jù)為空頁(yè)面布局變亂問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
vue 簡(jiǎn)單自動(dòng)補(bǔ)全的輸入框的示例
這篇文章主要介紹了vue 簡(jiǎn)單自動(dòng)補(bǔ)全的輸入框的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03

