前言
这是我参与新手入门的第1篇文章
前几天不是一百周年呢,看了看一百周年庆典,人的思绪回到了那篇被鲜血染红的年代,激情瞬间澎湃。然后,打开很多软件都是鲜红的一片,我又想起了之前接触的系统,想了想,还是想对之前主题的实现思路做个总结。
方案选择
- 在body节点上动态修改class名,根据不同的class名,写入不同的样式。每次切换,更改body上的类名,达到换肤效果
//类似于这样
body.red{
box{
color:red;
}
}
body.blue{
box{
color:blue;
}
}
复制代码
- 每种主题各写一个css文件,通过动态修改引入样式文件达到换肤。
这里,我想到如果是十几个主题,我如果选择第一种来写,极有可能就会复制漏掉几个,或者说内心就是极度抗住这种实现方式的。毫无疑问,我肯定选择第二种。毕竟样式文件的区分是极利于维护的。这里我也主要想说第二种实现方式,第一种通过度娘可以很快的度出来,当然也许大家有更好的实现方式,也欢迎大家留言,我去学习学习。
实现步骤
方案定了,那么肯定想着得怎么实现了。一个问题的解决总是得伴着几步走的。我的步骤就很简单了
- 准备一个下拉框,带有主题色和炫酷的主题名
- 每个主题准备一个样式文件
- 切换主题时读取对应的样式文件使其生效
- 后续优化问题,这里做到这里再考虑
1.准备一个可选择主题的样式
这个很简单,我选择的的是一个下拉框的形式,大家也可以选择排列的形式来展现。
2.每个主题一个单独的样式
这个也很简单,对每个主题创建一个对应的文件名样式文件即可,我的样式目录如下
这里我是用scss中的变量来实现一个样式文件中的所有主题色替换的,,至于为什么启用 .useable 作为样式文件后缀,我们后面说。顺便这里要将 ‘悲伤灰’的颜色单独说下。这里复制了网上的一段通用代码,进行整体的置灰,而不需要一个个样式的写。
html {
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: grayscale(100%);
filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
}
复制代码
这点也是最重要的一点,也是主题实现的核心 。首先我们得遍历所有的主题文件,然后每次下拉切换主题时,获取到对应的那一个文件并且引用。首先想到的就是用 VUEX状态管理将每次切换的状态存储下来,然后计算属性获取,每次切换,调用一个方法去获取当前的主题样式并引用,感觉这样的思路也能实现,但个人觉得还不够完美。在一番搜索之后,我找到了 style-loader的 useable 中 的 lazyStyleTag,并配合 css.use() 与 css.unuse() 达到了样式文件的完美引入与删除。这里 .useable作为文件后缀,也是style-loader的api推荐的 ,具体代码如下:
vue.config.js中
//全局配置scss文件的方法
const scss = config.module.rule("scss").toConfig();
//用.useable.scss是style-loader的api对应有 use 和 unuse 方法,动态加载删除link文件
const useable = {
...scss.oneOf[3],
test: /\.useable.scss$/
};
useable.use = [...useable.use];
useable.use[0] = {
loader: "style-loader",
options: {
injectType: "lazyStyleTag"
}
};
复制代码
其中 lazyStyleTag是用来延迟加载css文件的,我也是从这里lazyStyleTag才更好的理解此属性。
这里是我准备的主题json,文件名是 theme.js
const themes = [
{
value: "#000",
text: "经典",
name: "chalk",
},
{
value: "white",
text: "极光白",
name: "white"
},
{
value: "#266EB3",
text: "科技蓝",
name: "blue"
},
{
value: "#AF0009",
text: "中国红",
name: "red"
},
{
value: "#058F3D",
text: "护眼绿",
name: "green"
},
{
value: "#DBB579",
text: "高贵金",
name: "golden"
},
{
value: "gray",
text: "悲伤灰",
name: "gray"
},
{
value: "#DE0716",
text: "醒目红",
name: "lightred"
}
];
export default themes;
复制代码
所有的东西都准备好了,现在就只剩动态获取css文件了。这里,我的具体实现是这样的 style/theme/index.js
import themelist from "@/layout/components/theme";
const cache = {};
let themeAction = {};
themelist.forEach(theme => {
const item = theme.name || theme;
themeAction[item] = function() {
if (!cache[item]) {
cache[item] = require("./" + item + ".useable.scss").default;//.useable是style-loader中api,动态加载删除link文件
}
return cache[item];
};
});
let current = null;
export async function setTheme(theme){
let style = await themeAction[theme]();
//style-loader的api
if(current){
current.unuse();
//或style.unref();
}
style.use && style.use();
//或style.use && style.ref();
current = style
}
复制代码
这里需要注意的一点思想就是,每次切换的时候,我都会将本次的主题存起来,下次切换之前,删掉再引用,这样就不会一直累加引入的样式文件导致冲突啦,而且也算是一点小优化。
这里因为电脑原因,暂时没法贴上gif图了,就动态贴上几张截图展示下效果,忘各位见谅。
然后,非常感谢掘金的此次活动,让我迈开了动手写文章的第一步,也许此文有太多漏洞和组词不合适的地方,还望各位大佬见谅,谢谢。