今天在工作中偶然看到同组同事为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函数),从而大家都在各自的文件中各写各的,命名虽然一目了然,但无法拓展,不好维护
当不属于你的任务需要你来优化,这时要么先记下对方在文件里已经声明了哪些可复用函数,要么复制自己习惯的函数过来继续使用,不管哪一种都会导致效率低下),
而大家不写进公用文件里的原因是:这个活动需要用到,不一定其他活动用得到。暂且不评论这句话里的态度,但有一个很明显的问题:使用性受限制,拓展其实就是复制粘贴再改部分值。
回到正题,上面这种做法如果要实现下面的布局
![](https://img.haomeiwen.com/i13936697/df91048942c7bec4.png)
.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里基本需要使用该做法。现在思路如下:
- 变量使用... 与 mixin里使用 @arguments 来接收
- 混合里,我们需要实现传入多少变量,则调用多少次mixin,这里就需要使用到 length() 方法
- @arguments不能直接进行匹配,所以需要对变量集合进行提取,也就是需要用到 extract() 方法
- 使用 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对抗到底的文章),学而不思则罔,思而不学则殆,永远不要满足于能用,在会用以后,可以开发下脑洞,这对于开发很重要,以此共勉。
网友评论