less拓展 写一个flex函数

今天在工作中偶然看到同组同事为flex布局写了很多less混合

/* 布局辅助函数 */
.db(){
    display: -webkit-box;
    display: -webkit-flex;
    display: flex;
}
.flex-vm(){
    -webkit-box-pack: center;
    -webkit-justify-content: center;
    justify-content: center;
    -webkit-box-align: center;
    -webkit-align-items: center;
    align-items: center;
}
.flex-wrap(){
    -webkit-box-lines: multiple;
    -webkit-flex-wrap: wrap;
    flex-wrap: wrap;
}
.flex-justify(){
    -webkit-box-align: justify;
    -webkit-justify-content: space-between;
    justify-content: space-between;
}
.flex-dir-row(){
    -webkit-flex-direction: row;
    flex-direction: row;
    -webkit-box-orient: horizontal;
    -webkit-box-direction: normal;
}
.flex-dir-col(){
    -webkit-flex-direction: column;
    flex-direction: column;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
}

而自己在工作中也经常在对应的文件中写less混合。但是命名方式相对简单粗暴一点(只用首字母),是的我也是这么操作的一员…
这种做法导致了一个问题,大家都不想把自己写的东西写进fn.less里(组内公用less函数),从而大家都在各自的文件中各写各的,命名虽然一目了然,但无法拓展,不好维护
当不属于你的任务需要你来优化,这时要么先记下对方在文件里已经声明了哪些可复用函数,要么复制自己习惯的函数过来继续使用,不管哪一种都会导致效率低下),
而大家不写进公用文件里的原因是:这个活动需要用到,不一定其他活动用得到。暂且不评论这句话里的态度,但有一个很明显的问题:使用性受限制,拓展其实就是复制粘贴再改部分值

回到正题,上面这种做法如果要实现下面的布局

左右分布布局
.justify-block {
    .db();
    .flex-justify();
}

比方说写一个左右分布的布局,上面的代码看着似乎可以接受,但实际拼接起来的方式并不优雅,当你还需要添加其他规则的时候,上面继续再加混合,那么有可能变成下面这样:

.mixins {
    .db();
    .flex-dir-row();
    .flex-justify-end();
    .flex-align-center();
}

css里很多复合属性都不强制性需要使用者按照约束顺序,而且也不需要每个属性都写下去,部分值是存在默认值的。那么对到上述的问题也很简单,如果现在可以写一个函数,不要求顺序,不要求必须写下不必要的值,而且函数内部可以随意拓展后续需要使用的属性值,那问题便将迎刃而解。比方说下面这样:

.flex(wrap v justify-end align-center)

我们的目标是实现 .flex(wrap v justify-end align-center) 这样的书写形式,那么模式匹配必然是需要的。
我们可以使用...与@arguments来实现animation自定义入参,对到多变量的情况less里基本需要使用该做法。现在思路如下:

  1. 变量使用... 与 mixin里使用 @arguments 来接收
  2. 混合里,我们需要实现传入多少变量,则调用多少次mixin,这里就需要使用到 length() 方法
  3. @arguments不能直接进行匹配,所以需要对变量集合进行提取,也就是需要用到 extract() 方法
  4. 使用 loop 循环出所有提取到的匹配因子,执行 mixin() 调用

那么代码结果如下:

.flex(...){
    display: -webkit-box;
    display: -webkit-flex;
    display: flex;

    .mixin(wrap) {
        -webkit-box-lines: multiple;
        -webkit-flex-wrap: wrap;
            flex-wrap: wrap;
    }

    .mixin(v) {
        -webkit-box-orient: vertical;
        -webkit-flex-direction: column;
        flex-direction: column;
    }

    .mixin(align-center){
        -webkit-box-align: center;
        -webkit-align-items: center;
        align-items: center;
    }

    .mixin(justify-center){
        -webkit-box-pack: center;
        -webkit-justify-content: center;
        justify-content: center;
    }

    @length: length(@arguments);

    .loop(@length) when (@length > 0) {
        .loop((@length - 1));
        .mixin(extract(@arguments, @length));
    }

    .loop(@length);
}

思路没问题,却发现编译一直报错,打印后发现:循环里的 @arguments 不再是接收到的变量集合,而是变成了该集合的长度,这里也搜不到对应的原因跟资料,但通过科学上网发现,其实可以通过一个不定义长度的变量来代替默认提供的 @arguments。所以最终的代码变成如下:

.flex(@arg...){
    display: -webkit-box;
    display: -webkit-flex;
    display: flex;

    .mixin(wrap) {
        -webkit-box-lines: multiple;
        -webkit-flex-wrap: wrap;
        flex-wrap: wrap;
    }

    .mixin(v) {
        -webkit-box-orient: vertical;
        -webkit-flex-direction: column;
        flex-direction: column;
    }

    .mixin(align-center){
        -webkit-box-align: center;
        -webkit-align-items: center;
        align-items: center;
    }

    .mixin(justify-center){
        -webkit-box-pack: center;
        -webkit-justify-content: center;
        justify-content: center;
    }

    //arguments在循环里变成了长度了
    //解决办法:不要直接使用arguments,而是定义变量,并且是不限定长度的变量
    .loop(@i) when (@i > 0) {
        .loop((@i - 1));
        .mixin(extract(@arg, @i));
    }

    .loop(length(@arguments));
}

写到这里分享就结束了,我想通过匹配justify,然后再匹配是 center / flex-start / flex-end 等值实现混合里的mixin套mixin,然而less不能操作正则,匹配就只有上面一种模式,所以没办法,不过问题不大,毕竟已经实现了我想要的结果了。
这篇分享忽略了很多过程,直接给出本人思考结果。实际在实现时查阅过资料,却发现资料全是复制粘贴,跟官网文档没什么区别,对less的使用思考人数相当少(只找到一篇司徒大佬写的跟arguments对抗到底的文章),学而不思则罔,思而不学则殆,永远不要满足于能用,在会用以后,可以开发下脑洞,这对于开发很重要,以此共勉。

你可能感兴趣的:(less拓展 写一个flex函数)