1

本文主要是记录自己日常工作中用到过的一些less小技巧

1. 组件库主题定制

一般组件库的样式编写都会为使用者设计一些主题样式更换方案,我这里根据自己对主流组件库antd和iview的研究,总结出这两类:

iview引入主题样式,复写

@import '~iview/src/styles/index.less';
// Here are the variables to cover, such as:
@primary-color: #1B88EE;

antd通过less-loader的modifyVars注入主题变量

rules: [{
    test: /\.less$/,
    use: [{
        loader: 'style-loader',
    }, {
        loader: 'css-loader', // translates CSS into CommonJS
    }, {
        loader: 'less-loader', // compiles Less to CSS
        options: {
            modifyVars: {
                'primary-color': '#1B88EE',
            },
            javascriptEnabled: true,
        },
    }]
}] 
//注意 less-loader 的处理范围不要过滤掉 node_modules 下的 antd 包。

所以在给公司定制组件库的时候我们可以使用这两种方法来给使用者定制主题,当然了,我们设计的时候最好和主流框架的变量名保持一致,使得使用者更好上手。

@primary-color: #1B88EE;                         // 全局主色
@link-color: #1B88EE;                            // 链接色
@success-color: #4FC7AF;                         // 成功色
@warning-color: #F8AC59;                         // 警告色
@error-color: #F95355;                           // 错误色
@font-size: 28px;                                // 主字号
@text-color: rgba(0, 0, 0, .65);                 // 主文本色
@text-color-secondary : rgba(0, 0, 0, .45);      // 次文本色
@disabled-color : rgba(0, 0, 0, .25);            // 失效色
@border-radius: 4px;                             // 组件/浮层圆角
@border-color: #d9d9d9;                          // 边框色
@box-shadow-base: 0 2px 8px rgba(0, 0, 0, .15);  // 浮层阴影

2. 给项目设置常用样式common.less

不知道大家在实际开发中有没有遇到过为了一个 paddingmarginfontsize 而常常需要多写一层class的情况。

.loop(20);
.loop(@n, @i: 0) when (@i =< @n) {
    @size: @i*2;

    .pt-@{size} { padding-top: unit(@size, px) !important; }
    .pr-@{size} { padding-right: unit(@size, px) !important; }
    .pb-@{size} { padding-bottom: unit(@size, px) !important; }
    .pl-@{size} { padding-left: unit(@size, px) !important; }

    .mt-@{size} { margin-top: unit(@size, px) !important; }
    .mr-@{size} { margin-right: unit(@size, px) !important; }
    .mb-@{size} { margin-bottom: unit(@size, px) !important; }
    .ml-@{size} { margin-left: unit(@size, px) !important; }

    .fs-@{size} { font-size: unit(@size, px) !important; }

    .loop(@n, (@i + 1));
}
// e.g. pt-2 pt-16 pt-40 fs-16 fs-24等等

把以上这段加到通用less里后,如果有一些特殊的边距或字体就可以直接写 class="mb-20" 这样了,可以省去一些功夫多写个不必要的class,当然常用的 widthheight 之类的都可以通过when循环解决,需要注意的less没有if-else判断,所有的判断也都是通过when关键字来解决。

更新补充:lessv3.9实现each循环写法,v3.0也已实现if判断
更新后写法如下:

each(range(2, 40 ,2), {
    .p-@{value} { padding: @value * 1px !important; }
    .pt-@{value} { padding-top: @value * 1px !important; }
    .pr-@{value} { padding-right: @value * 1px !important; }
    .pb-@{value} { padding-bottom: @value * 1px !important; }
    .pl-@{value} { padding-left: @value * 1px !important; }

    .m-@{value} { margin: @value * 1px !important; }
    .mt-@{value} { margin-top: @value * 1px !important; }
    .mr-@{value} { margin-right: @value * 1px !important; }
    .mb-@{value} { margin-bottom: @value * 1px !important; }
    .ml-@{value} { margin-left: @value * 1px !important; }

    .fs-@{value} { font-size: @value * 1px !important; }
});

3. 习惯使用Mixins

什么是mixins?
中文翻译为“混合”,把一些规则级别的样式复用归为可带参函数。
常见的有:

.ellipsis(@w: auto) {
    width: @w;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    word-wrap: normal;
}
// for iphoneX+
.safe-area-inset-bottom() {
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
}
.hairline-bottom(@left: 0, @right: 0, @border-color: @border-color) {
    position: relative;
    &::after{
        position: absolute;
        content: "";
        top: auto;
        right: @right;
        bottom: 0;
        left: @left;
        border-bottom: 1px solid @border-color;
        transform: scaleY(0.5);
    }
}

使用方法:

body {
    .safe-area-inset-bottom();
}
// 编译后的CSS代码
body {
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
}

4. 实现random函数

自己 lesssass 都用过,使用上最大的区别就是 less 缺少了random函数,对于实现一些高级效果会有影响,那如何在 less 中实现random函数呢?

通过配置 javascriptEnabled: true 允许执行内联js代码:

<style lang="less">
body {
    top: ~`Math.random() * 100 + 'px'`;
}
</style>

由于安全隐患上述配置将会废弃,在3.0版本默认设置为false,通过 @plugin 取代:

// less-plugin.js
module.exports = {
    install: function(less, pluginManager, functions) {
        functions.add('random', function() {
            return new less.tree.Dimension(Math.random());
        });
    }
};
<style lang="less">
@plugin "less-plugin";
body {
    top: random() * 100px;
    background: rgba(0, 0, 0, random());
}
</style>

通过 plugin-atrules-feature 特性,还能实现一些很高级的写法,例如 cssjs 代码的联动。假设我们有一个颜色预设数组:

const colors = ['success', 'warning', 'error'];

然后通过上述类似的方式新增插件:

functions.add('getColorNames', function() {
    return colors.toString();
});
<style lang="less">
@plugin "less-plugin";
@colorNames: getColorNames();
@colors: #2ac864 #ff7f24 #f85a54;
each(@colorNames, {
    .c-color-@{value} {
        color: extract(@colors , @index);
    }
});
</style>

就能实现当需要新增数组中的颜色枚举值时,style 样式代码无需额外实现一遍,cssjs 用同一个变量控制,达到联动效果。当然这里只是个简单demo,真正实现的时候可以考虑抽出colors变量,达到样式完全隔离的效果。

5. @import指令使用~作为alias

@import简介

  • 如果扩展名是 .css,文件内容将被原样输出。 @import './style.css'
  • 如果是任何其他扩展名,将作为.less文件被导入。 @import './style'
  • 如果存在~符号,将alias和地址拼接成最后的地址。 @import '~@/assets/variable.less'

常常会在vue项目中看到这样的情形:

@import '../../../assets/variable.less'

可以简写为以下:

@import '~@/assets/variable.less'

这里的~符号表示后面的值为 alias, 就会去webpack的alias配置中找相应的值。
更新补充:webpack的less-loader已默认options.webpackImporter为true,所以~作为alias的配置已废弃,当然,~符号还有它存在的意义,当无法从import中找到地址时,会从node_modules中查找!!!正常情况下@import '@/assets/variable.less'即可


小皇帝James
600 声望7 粉丝

IT吴彦祖