我正在使用vue和webpack编写单个文件组件,并使用less-loader
来解析组件文件中的<style lang="less"></style>
字段
我正在寻找一种能够为网站编写主题的好方法。理想情况下,我想像这样拥有单独的theme.less
文件:
src
|--themes
| |-- light.less
| |-- dark.less
|--components
|-- app.vue
|-- nav.vue
theme.less文件由通用变量组成的地方:
@bg: hsl(251, 44%, 95%);
@sub: hsl(251, 18%, 81%);
@surface: hsl(251, 18%, 81%);
@text: hsl(0, 0%, 0%);
@link: ...
这样我就可以以主题无关的方式编写组件级样式:
<style lang="less">
#main-content {
background-color: @bg;
color: @text;
border: @primary;
}
</style>
并生成将我提供的样式包装在主题类中的css:
.light #main-content {
background-color: [@bg variable in light.less];
color: [@text variable in light.less];
border: [@primary variable in light.less];
}
.dark #main-content {
background-color: [@bg variable in dark.less];
color: [@text variable in dark.less];
border: [@primary variable in dark.less];
}
这样我就可以将主题类应用于<body class="dark">
之类的根元素并显示适当的样式。
最好的方法是什么?
当前,我已经实现了自己的解决方案,该解决方案使用了inject
提供的style-resources-loader
功能:
module.exports = function (source, resources) {
let newSource = source.trim();
let themes = resources.map(v => {
let o = {};
o.default = v.content.startsWith("/**DEFAULT**/");
o.name = v.file.split('/').pop().replace(/\.[^/.]+$/, "");
return o;
});
let wrappers = themes.map(v => `
${v.default ? 'body' : '.' + v.name} {
@import (reference) '../themes/${v.name}.less';
`);
let compiled = "";
wrappers.forEach(w => {
compiled += w + newSource + '\n}\n';
})
return compiled
}
这是针对每个组件的style
代码的,它会创建多个主题类块,例如
.light {
@import (reference) '../themes/light.less';
[injected source code]
}
.dark {
@import (reference) '../themes/dark.less';
[injected source code]
}
并在导入后插入样式代码,从而允许将组件中的@variable
引用的范围限定为主题,并输出包含包装在多个主题类中的所有样式的css(因此复制了我为之编写的所有样式我可以使用的每个主题)
我主要是问是否有更好的方法可以实现此目的,可能是通过webpack,vue或一些我所忽略的内置功能实现的。
谢谢!
答案 0 :(得分:0)
我有完全相同的需求。但是,我选择了另一种使用CSS Custom Properties(又称CSS变量)的方法。
重构您的LESS变量,例如:
@bg: var(--bg, lime);
@sub: var(--sub, lime);
@surface: var(--surface, lime);
@text: var(--text, lime);
@link: ...
然后为每个主题定义CSS变量:
:root {
--bg: hsl(251, 44%, 95%);
--sub: hsl(251, 18%, 81%);
--surface: hsl(251, 18%, 81%);
--text: hsl(0, 0%, 0%);
--link: ...
}
基本上,这就是您需要的一切。它工作得很好,甚至具有额外的好处,我什至可以使用开发工具直接在浏览器中播放颜色,或者将它们添加为用户设置,以允许用户定义自己的主题。