webpack less 抽取小技巧 - css多主题使用篇
2023-03-15 本文已影响0人
suliang2010
序
上一篇 webpack less 抽取小技巧 中说到,可以进行多主题的引入。此篇咱们就来实现一下如何引入多个css主题;
基本环境介绍
前置:
- 已经存在多套css主题放置在服务端
- 使用切换按钮 (或者其他交互切换)
css 主题切换思路讲解
*方案一 link 引入,每次切换的时候,更换href,动态引入css;(用浏览器本身的 304 获取缓存,但是这种容易被浏览器限制)
*方案二 ajax获取资源,配合style写入样式,切换的时候,多次获取资源 (由于多次获取资源,可以在本地缓存已经请求的资源,同一份资源不做二次请求)(由于ajax请求,所以受浏览器请求的限制,比如请求并发限制(如下图),所造成浏览器响应时间过高)

- 终极方案 根据方案二出现的问题,将方案一二进行整理;实现思路如下:首页添加默认的link css链接,在进行主题切换的之后,继续执行缓存策略,并将link删除;好处:这种能避免在第一次ajax请求之前导致的样式错乱问题;缺陷:需要进行ajax 请求的资源才能获取
代码呈现:
功能代码:
// base vue , 但是功能本身不依赖框架,反倒是对浏览器dom有依赖
// 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) {
// 扩展的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);
// })
// 请求优化
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);
},
配合的页面:
// 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>
以上,有问题请留言讨论,谢谢大家~