用@each遍历map是生成间距类的唯一可靠方式;@for仅产数字序列无法表达sm/md/lg语义,手写易漏值、单位不一、难维护;需正确解构键值对、使用字符串键名和插值语法,并通过mixin复用同一map驱动多属性。

直接结论:用 @each 遍历 Map,配合插值生成类名和声明,是唯一能保证全覆盖、单位统一、逻辑集中的方式;离散变量或手写类名极易漏值、错单位、难维护。
为什么不能用 @for 或手写循环生成间距类?
间距类(如 .p-2、.m-lg)需要“键名语义 + 值精确对应”,而 @for $i from 1 through 8 只能产出数字序列,无法表达 sm/md/lg 的设计意图,也不便于后续映射到设计系统文档。
- 手写易漏:比如写了
.p-sm和.p-md,但忘了.p-xs或.p-xl - 单位不一致:有人写
4px,有人写0.25rem,审查时才发现不统一 - 改一个值要全局搜替换,
$spacing-sm可能被硬编码在某处没被变量覆盖
@each $key, $value in $map 必须成对解构,别把整个 map 当 value
常见错误是写成 @each $bp in $breakpoints,结果 $bp 实际是 ("sm": 576px) 这个键值对,导致 @media (max-width: $bp) 编译失败 —— 因为 $bp 不是数值,而是 map。
- 正确写法:
@each $name, $value in $breakpoints,然后用$value直接参与计算 - 键名必须是字符串字面量:
"sm"✅,sm❌(会被解析为未定义变量) - 插值类名必须带花括号:
.p-#{$key}✅,.p-$key❌(输出字面量$key)
批量生成响应式工具类时,如何复用同一套 Map?
一套 $spacing Map 可同时驱动 padding、margin、gap 类,只需改变属性名和前缀,不用重复定义数值。
- 避免复制粘贴 Map:不要为 padding 单独建
$padding-map,它和$spacing本质是同一组值 - 用 mixin 封装共性逻辑:
@mixin generate-spacer($prop, $prefix),内部调用@each - 注意单位转换:若 Map 存的是
rem,但某些场景需转px,应在@each体内用math.div()或自定义函数处理,而非提前转好存进 Map
Map 嵌套时取值容易掉坑:深层 key 必须用 map-get() 链式调用
比如 $theme: ("light": (color: (text: #333, bg: #fff))),想取 light 下的 text,不能写 map-get($theme, "light text") —— Sass 不支持路径字符串语法。
- 正确方式:
map-get(map-get(map-get($theme, "light"), color), text) - 更安全做法:封装
@function theme($path...),用@each递归遍历$path数组(注意:Sass 不支持动态 key,所以$path必须是字面量列表,如"light" "color" "text") - 加防御检查:
@if not map-has-key($submap, $key),避免null被意外输出为 CSS 值
真正麻烦的不是写一遍 @each,而是当设计系统新增一个断点、一种颜色角色、一类组件状态时,你得确认所有相关 @each 循环是否都覆盖到了——Map 结构本身不报错,但漏了就真漏了,且没有运行时提示。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











