Less原生不支持each和range函数,必须用递归mixin模拟遍历,需严格设置守卫条件、索引起始值(从1开始)及终止边界,否则将导致编译报错或漏项。

Less里根本没有each和range函数
Less原生不支持each或range这类高阶函数——这是Sass的语法。如果你在Less代码里直接写each($i in range(1, 5)),编译会报错:ParseError: expected ")" got "in"。Less的循环能力仅靠「递归mixin」实现,必须手动控制终止条件。
用递归mixin模拟range生成间隔类(如mt-1到mt-24)
核心思路是定义一个带计数器的mixin,每次调用自身并递减/递增参数,直到达到边界值。注意必须显式设置停止条件,否则无限递归导致编译卡死。
.make-spacing-classes(@i: 1, @max: 24) when (@i =< @max) {
.mt-@{i} { margin-top: (@i * 0.25rem); }
.mb-@{i} { margin-bottom: (@i * 0.25rem); }
.ml-@{i} { margin-left: (@i * 0.25rem); }
.mr-@{i} { margin-right: (@i * 0.25rem); }
// 递归调用下一项
.make-spacing-classes((@i + 1), @max);
}
// 启动入口
.make-spacing-classes();- 必须写
when (@i =守卫条件,否则Less无法判断何时停止 -
@i不能用++或+=,Less变量不可变,只能通过参数传递新值 - 如果
@max设得过大(比如>100),Less编译器可能因递归深度超限报错:Recursion limit exceeded
生成非等差间隔(如gap-2、gap-4、gap-8)怎么办
递归mixin也能处理自定义序列,只需把数值列表转为参数序列,再用匹配模式逐个解构。Less不支持数组遍历,但支持「多参mixin匹配」这种变通方式。
.make-gap-classes(2, 4, 8, 12, 16, 24);
.make-gap-classes(@a, @b, @c, @d, @e, @f) {
.gap-@{a} { gap: (@a * 0.25rem); }
.gap-@{b} { gap: (@b * 0.25rem); }
.gap-@{c} { gap: (@c * 0.25rem); }
.gap-@{d} { gap: (@d * 0.25rem); }
.gap-@{e} { gap: (@e * 0.25rem); }
.gap-@{f} { gap: (@f * 0.25rem); }
}- 每个数值必须硬编码在mixin调用参数中,无法动态读取外部JSON或计算生成
- 参数数量要和mixin定义严格一致,少一个或多一个都会导致匹配失败,该规则被跳过
- 若需更多值,得手动扩写参数列表和对应规则,维护成本明显上升
为什么不用JavaScript插件或PostCSS替代
Less编译时无JS运行环境,所谓「Less插件」实际是Node.js层的编译器扩展,配置复杂且破坏工具链一致性。而PostCSS虽然灵活,但会让样式逻辑分散在两个系统里:Less管变量和嵌套,PostCSS管生成,调试时得来回切换上下文。
立即学习“前端免费学习笔记(深入)”;
- 如果项目已用Webpack+Less-loader,强行加Less插件需额外写
less-plugin-custom并注入编译流程 - PostCSS方案(如
postcss-prefixwrap或自定义插件)虽能生成类名,但无法直接复用Less变量(如@spacing-unit),容易产生值不一致 - 最轻量的做法仍是守住Less能力边界:用递归mixin + 合理的
@max上限(建议≤32),兼顾可读性与生成效率
递归深度、参数硬编码、守卫条件缺一不可——漏掉任何一点,生成结果就不可控。


















