less 的 guard 表达式仅在编译期根据传入变量值静态匹配分支,无法自动生成多个 css 文件;实现多版本输出需借助构建工具(如 sass cli、webpack、vite)多次独立编译并注入不同变量值。

Less 的 Guard 表达式本身不能实现“一个源码、多套 CSS 输出”,它只控制编译期哪段样式被写入当前输出文件;要真正达成 CSS 版本差异化打包,必须配合构建工具多次独立编译,并在每次编译时传入不同变量值。
Guard 本身不生成多个 CSS 文件
Guard 是编译期静态匹配机制,不是运行时分支逻辑。你写:
.btn(@theme) when (@theme = "dark") { background: #111; }<br>.btn(@theme) when (@theme = "light") { background: #fff; }
——这不会自动产出 dark.css 和 light.css。它只在当前编译中,根据传入的 @theme 值决定保留哪一分支。没传值?或值不匹配?对应分支直接被跳过,什么都不会输出。
- Guard 不感知构建上下文,它只认编译那一刻已确定的变量值
- 没有
@else或兜底分支时,非匹配值会导致整个 mixin 无样式输出 - 想让
.btn("dark")生效,必须确保调用前@theme已被赋值为"dark"(不能靠 JS 动态改)
必须用 CLI 或构建工具传参触发不同编译
真正起作用的是外部变量注入,不是 Guard 本身。例如用 Dart Sass CLI:
sass --define=theme="dark" main.less:dist/dark.css<br>sass --define=theme="light" main.less:dist/light.css
此时 @theme 在编译开始前就被设为字符串字面量,Guard 才能正确匹配。
- Webpack 中需用
DefinePlugin注入:new webpack.DefinePlugin({ THEME: JSON.stringify("dark") }),然后 Less 里写when (@theme = THEME) - Vite 用户可通过
build.define配置,但注意 Less 插件是否支持变量注入(vite-plugin-less 默认支持lessOptions.modifyVars) - 变量名必须统一:CLI 传
--define=theme="dark",Less 里就得用@theme,不能写成@THEME或漏引号
Guard 分支必须覆盖所有传入值,且顺序敏感
多个同名 mixin + Guard 构成“重载”,编译器按定义顺序匹配第一个为 true 的分支,之后停止。漏掉兜底或顺序错,就会丢样式。
.theme-bg(@t) when (@t = "dark") { background: #000; }<br>.theme-bg(@t) when (@t = "light") { background: #fff; }<br>.theme-bg(@t) when not (@t = "dark"), not (@t = "light") { background: #f0f0f0; }
- 最后一条用逗号表示 “or”,等价于
not ((@t = "dark") or (@t = "light")),比单个not (@t = "dark")更安全 - 字符串比较必须加引号:
@t = "dark"✅,@t = dark❌(后者查变量@dark,未定义则守卫失效) - 类型必须一致:
@t: 123和@t = "123"永远不匹配,建议统一用字符串传参
容易被忽略的初始化与作用域问题
Guard 不会帮你初始化变量,也不跨文件继承值。如果 @theme 在某个 .less 文件里没声明,又没通过 CLI 注入,那所有分支都静默失效——不会报错,只是没输出。
- 顶层应显式初始化:
@theme: "default";,再配合兜底分支,避免空值导致样式消失 - 变量作用域是文件级的,
@import不会自动提升变量,需确保传参变量在 Guard 使用前已生效 - 不要试图在 Guard 里调用
unit()、replace()或拼接字符串——这些在编译期不可用,会直接报错或跳过分支
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











