【问题标题】:How to create themes in vue/webpack using LESS如何使用 LESS 在 vue/webpack 中创建主题
【发布时间】:2019-06-19 17:00:48
【问题描述】:

我正在使用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];
}

这样我就可以将主题类应用到像&lt;body class="dark"&gt; 这样的根元素并显示适当的样式。

最好的方法是什么?



目前我已经实现了自己的解决方案,它使用了style-resources-loader 提供的inject 功能:

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 或我忽略的一些内置功能。

谢谢!

【问题讨论】:

    标签: javascript css vue.js webpack less


    【解决方案1】:

    我也有同样的需求。但是,我选择了另一种方法,使用 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:    ...
    }
    

    这基本上就是您需要的一切。它工作得非常好,甚至还有一个额外的好处,我什至可以使用开发工具直接在浏览器中使用颜色,或者将它们添加为用户设置以允许用户定义自己的主题。

    【讨论】:

    • 那么使用这个解决方案,您是否可以在 dark.less 和 light.less 文件中定义 CSS 变量,然后将它们导入到 main.less 文件中?
    • 这是一个简单的用法,是的。您必须根据需要自行决定是否加载所有主题并通过例如切换它们。切换(类)属性,例如body-element 或在按需加载主题的情况下制作更高级的东西。
    猜你喜欢
    • 1970-01-01
    • 2019-09-06
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    • 2017-05-23
    • 2016-10-30
    • 1970-01-01
    • 2021-04-01
    相关资源
    最近更新 更多