使用@use ... with覆盖Sass颜色映射失败:变量未定义
我们的仓库结构如下:public/scss/下存放网站基础样式的默认SCSS文件,base/themes中的内容可覆盖src中的内容。常规SCSS覆盖功能正常,但尝试在customer_theme.scss中覆盖variables中的颜色映射时,要么不生效,要么导致编译器(sass embedded linux x64 v1.83.4)无法生成.css文件。
├── src/ │ └── layouts/ │ └── public/ │ └── scss/ │ └── _variables.scss └── base/ └── themes/ └── customer_theme/ └── public/ └── scss/ └── customer_theme.scss
默认的_variables.scss中定义了基础颜色映射:
@use "sass:map"; @use "sass:color"; // ROOT $scale : 2 !default; $base-font-size: calc(16px + .02vw) !default; // COLORS $colors: ( primary: #526066, corporate: #000000, light: #ffffff, accent: #1ebdff, neutral: #cecece, warning: #ff0000, offered: #554BDD, hint: #ffdd00, confirmed: #00af00) !default;
customer_theme.scss中的映射代码如下:
@use "sass:map"; @use "sass:color"; @use "layout/variables" as * with ($scale: 2, $base-font-size: calc(16px + .02vw), $font_1: "Source Sans 3", $colors: map.merge($colors, (primary: #02305F, corporate: #000000, light: #ffffff, accent: #E30916, neutral: #cecece, warning: #ff0000, offered: #554BDD, hint: #ffdd00, confirmed: #00af00, )));
构建时出现如下错误:
panic: Error compiling scss: 400 Bad Request: message: Undefined variable. stack: theme/customer_theme.scss 6:29 @use - 15:1 root stylesheet
问题
为何使用with覆盖$colors映射会出现未定义变量错误?
编辑补充:尝试过使用@forward "variables",解决了构建逻辑导致的另外两个错误后,仍出现相同的初始错误。
解答
核心原因是:在@use ... with语句中,你试图引用的$colors变量此时还未被定义。
SCSS处理@use ... with的逻辑是先解析覆盖参数,再加载目标模块。也就是说,当你写map.merge($colors, ...)的时候,$colors还没从layout/variables模块导入,当前作用域里根本不存在这个变量,自然会报“Undefined variable”错误。
有两种解决方法:
方法一:直接定义完整的新映射
既然要覆盖,直接写出完整的颜色映射,不需要依赖原变量:
@use "sass:map"; @use "sass:color"; @use "layout/variables" as * with ( $scale: 2, $base-font-size: calc(16px + .02vw), $font_1: "Source Sans 3", $colors: ( primary: #02305F, corporate: #000000, light: #ffffff, accent: #E30916, neutral: #cecece, warning: #ff0000, offered: #554BDD, hint: #ffdd00, confirmed: #00af00, ) );
方法二:先导入模块获取原变量,再重新配置
如果不想重复写完整映射,可以先导入模块(不带with)拿到原$colors,再合并新值后重新加载模块:
@use "sass:map"; @use "sass:color"; // 先导入原模块,获取默认变量 @use "layout/variables" as vars; // 合并新的颜色值 $custom-colors: map.merge(vars.$colors, ( primary: #02305F, accent: #E30916, )); // 重新加载模块并传入覆盖后的变量 @use "layout/variables" as * with ( $scale: 2, $base-font-size: calc(16px + .02vw), $font_1: "Source Sans 3", $colors: $custom-colors );
注意:第二种方法需要确保构建流程支持重复导入,只要原变量带!default标记,这种写法就是合法的。
内容的提问来源于stack exchange,提问作者MrJoky

