序
上一篇 webpack less 抽取小技巧 中說(shuō)到按傅,可以進(jìn)行多主題的引入毙替。此篇咱們就來(lái)實(shí)現(xiàn)一下如何引入多個(gè)css主題;
基本環(huán)境介紹
前置:
- 已經(jīng)存在多套css主題放置在服務(wù)端
- 使用切換按鈕 (或者其他交互切換)
css 主題切換思路講解
*方案一 link 引入怀挠,每次切換的時(shí)候免糕,更換href善镰,動(dòng)態(tài)引入css;(用瀏覽器本身的 304 獲取緩存谤饭,但是這種容易被瀏覽器限制)
*方案二 ajax獲取資源标捺,配合style寫(xiě)入樣式,切換的時(shí)候揉抵,多次獲取資源 (由于多次獲取資源亡容,可以在本地緩存已經(jīng)請(qǐng)求的資源,同一份資源不做二次請(qǐng)求)(由于ajax請(qǐng)求冤今,所以受瀏覽器請(qǐng)求的限制闺兢,比如請(qǐng)求并發(fā)限制(如下圖),所造成瀏覽器響應(yīng)時(shí)間過(guò)高)
- 終極方案 根據(jù)方案二出現(xiàn)的問(wèn)題戏罢,將方案一二進(jìn)行整理屋谭;實(shí)現(xiàn)思路如下:首頁(yè)添加默認(rèn)的link css鏈接,在進(jìn)行主題切換的之后龟糕,繼續(xù)執(zhí)行緩存策略桐磁,并將link刪除;好處:這種能避免在第一次ajax請(qǐng)求之前導(dǎo)致的樣式錯(cuò)亂問(wèn)題讲岁;缺陷:需要進(jìn)行ajax 請(qǐng)求的資源才能獲取
代碼呈現(xiàn):
功能代碼:
// base vue , 但是功能本身不依賴(lài)框架我擂,反倒是對(duì)瀏覽器dom有依賴(lài)
// template
<!-- 切換皮膚一 -->
<li @click="_changeThemeFun('1')">
<sf-svg-icon iconClass="state-portal"></sf-svg-icon>
<span>換膚一</span>
</li>
<!-- 切換皮膚一 -->
<li @click="_changeThemeFun('2')">
<sf-svg-icon iconClass="state-portal"></sf-svg-icon>
<span>換膚二</span>
</li>
//.....
// 換膚
async _changeThemeFun(type) {
// 擴(kuò)展的theme映射
// const transTheme = {
// ['0']: '0',
// ['1']: '1',
// ['2']: '2',
// };
// 不存在則渲染 + 加載
// 存在則清除后渲染 + 加載
const theme = document.querySelector('#theme-link');
console.log('theme', theme);
// css link
// this.loadCSS(`/theme/theme${type}.css`);
// style
// axios.get(`/theme/theme${type}.css`).then(res => {
// const cssText = res.data || '';
// this.loadStyle(cssText);
// })
// 請(qǐng)求優(yōu)化
const cssText = await this.getCssTextFun(type);
this.loadStyle(cssText);
// 存在,則清除
if (theme) {
// theme.remove();
let themeParent = theme.parentElement;
themeParent.removeChild(theme);
}
},
async getCssTextFun(type) {
if (!this.theme[type]) {
return axios.get(`/theme/theme${type}.css`).then(res => {
const cssText = res.data || '';
this.theme[type] = cssText;
return Promise.resolve(this.theme[type]);
});
} else {
return Promise.resolve(this.theme[type]);
}
},
loadStyle(cssText) {
const STYLE_ID = 'style-css';
const target = document.getElementById(STYLE_ID);
const setCssTxt = (style, cssText) => {
try {
// firefox催首、safari扶踊、chrome和Opera
// style.clear();
console.log('style', style);
// style.innerText = '';
// style.appendChild(document.createTextNode(cssText));
style.innerText = cssText;
} catch (ex) {
// IE早期的瀏覽器 ,需要使用style元素的stylesheet屬性的cssText屬性
style.styleSheet.cssText = cssText;
}
};
if (target) {
setCssTxt(target, cssText);
return;
}
const style = document.createElement('style');
style.setAttribute('id', STYLE_ID);
setCssTxt(style, cssText);
document.head.appendChild(style);
},
loadCSS(url) {
const LINK_ID = 'url-link';
// 存在
const target = document.getElementById(LINK_ID);
if (target) {
target.setAttribute('href', url);
return;
}
// 不存在
const element = document.createElement('link');
element.setAttribute('rel', 'stylesheet');
element.setAttribute('type', 'text/css');
element.setAttribute('id', LINK_ID);
element.setAttribute('href', url);
document.head.appendChild(element);
},
配合的頁(yè)面:
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<link rel="stylesheet" href="<%= BASE_URL %>css/element/index.css">
<!-- css 引入 -->
<link rel="stylesheet" id="theme-link" type="text/css" href="<%= BASE_URL %>theme/theme.css">
</head>
</html>
以上,有問(wèn)題請(qǐng)留言討論郎任,謝謝大家~