detached rulesets 是 less 中唯一支持样式块作为变量存储、按需展开及跨 mixin 传递的机制;声明需加分号、调用必须加(),否则规则不生效;作用域求值在调用时发生,支持+注入或()执行,但语义不同,跨文件须@import (reference)。

Detached Rulesets 不是“高级技巧”,而是 Less 里唯一能让你把样式当变量存、按需展开、跨 mixin 传递的机制——它解决的是「写一次,不立即输出,等我点名才生效」这个刚需。
Detached Rulesets 声明和调用必须带括号
声明时结尾要加分号,调用时必须加 (),否则规则不会展开,编译后完全消失。
- ✅ 正确:
@btn-base: { color: @primary; border: 1px solid desaturate(@primary, 20%); };+.btn { @btn-base(); } - ❌ 错误:
@btn-base: { ... }(少分号);.btn { @btn-base; }(没括号,只当变量名输出);+ @btn-base(+ 和变量间有空格) - ⚠️ 注意:
@btn-base()是执行;@btn-base[@color]是取属性值(此时括号可省)
传给 mixin 时必须显式调用 (),否则只是引用
很多同学以为把 ruleset 当参数传进 mixin 就自动生效了,其实 mixin 内部不写 @styles(),它就永远只是个变量。
- ✅ 安全写法:
.card(@styles: false) when (isruleset(@styles)) { @styles(); }—— 先用isruleset()判断,再执行 - ❌ 危险写法:
.card(@styles) { @styles; }→ 编译失败或静默丢弃 - ? 作用域关键点:变量求值发生在调用时,不是定义时。所以
@color: red; .use() { @r(); }输出的是red,哪怕@r里写了color: @color;且定义在@color: blue;之后
用 + 注入 vs () 执行,语义完全不同
+ 是把规则块“贴进当前选择器上下文”,() 是“立刻执行该规则集”,二者不能互换,尤其涉及 & 时。
- ✅
.card-header { +@header-style; }→@header-style内的&__title会编译成.card-header__title - ❌
.card-header { @header-style(); }→ 如果@header-style含&__title,会因顶层无父选择器报错 - ?
+只能在选择器内部使用;()可在任何合法作用域调用,但要求规则集自身结构完整(比如不能裸写&:hover)
跨文件使用必须 @import (reference)
Detached Rulesets 是变量,不是全局声明。没加 (reference) 的 @import 会导致变量不可见,调用直接失效,且通常无报错。
- ✅ 正确:
@import (reference) "base/rulesets.less";→ 规则集可被下游文件访问 - ❌ 错误:
@import "base/rulesets.less";→ 即使文件存在,@btn-base在业务文件里就是 undefined - ⚠️ 特别注意:
@media内部直接定义 ruleset 再调用,在部分 less-loader 版本中会报错,建议提前定义在顶层
真正难的不是语法怎么写,而是判断什么时候该用 detached ruleset、什么时候该抽成 BEM 类、什么时候该用 :extend() —— 它们解决的问题层次不同,混用反而增加维护成本。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











