遍历 @each
约 1324 字大约 4 分钟
2025-04-11
在 Sass 中,@each
是一个控制指令,用于遍历列表(List)或映射(Map)中的元素,并根据元素值动态生成样式代码。它是处理重复性样式逻辑的高效工具,特别适合管理集合数据(如颜色、尺寸、断点等)。以下是 @each
的详细介绍、用法和特性:
一、核心特性
遍历集合数据:支持遍历简单列表、嵌套列表和映射(Map)。
动态生成样式:根据集合中的元素生成规律性强的类名或样式。
代码简洁性:替代手动重复代码,提升开发效率和可维护性。
灵活性:可与变量、函数、混合宏(Mixin)结合,实现复杂逻辑。
二、基础语法
// 遍历列表或映射中的每个元素
@each $变量 in <集合> {
// 循环体:使用 $变量 生成代码
}
三、不同数据结构的遍历方法
1、遍历简单列表(List)
生成不同颜色的按钮类:
$colors: red, blue, green;
@each $color in $colors {
.btn-#{$color} {
background: $color;
border: 1px solid darken($color, 10%);
}
}
编译后:
.btn-red {
background: red;
border: 1px solid #cc0000;
}
.btn-blue {
background: blue;
border: 1px solid #0000cc;
}
.btn-green {
background: green;
border: 1px solid #004d00;
}
2、遍历嵌套列表(Nested List)
同时遍历多个属性(如类名、背景色、文本色):
$theme-list: ("primary", blue, white), ("secondary", gray, black);
@each $name, $bg, $text in $theme-list {
.theme-#{$name} {
background: $bg;
color: $text;
}
}
编译后:
.theme-primary {
background: blue;
color: white;
}
.theme-secondary {
background: gray;
color: black;
}
3、遍历映射(Map)
管理响应式断点并生成媒体查询:
$breakpoints: (
"sm": 576px,
"md": 768px,
"lg": 992px,
);
@each $name, $size in $breakpoints {
@media (min-width: $size) {
.container-#{$name} {
max-width: $size;
}
}
}
编译后:
@media (min-width: 576px) {
.container-sm {
max-width: 576px;
}
}
@media (min-width: 768px) {
.container-md {
max-width: 768px;
}
}
@media (min-width: 992px) {
.container-lg {
max-width: 992px;
}
}
四、高级用法与技巧
1、结合索引生成序列化样式
为列表元素添加递增的 z-index
:
$layers: header, sidebar, modal;
@each $layer in $layers {
$index: index($layers, $layer); // 获取元素索引
.#{$layer} {
z-index: $index * 10;
}
}
编译后:
.header {
z-index: 10;
}
.sidebar {
z-index: 20;
}
.modal {
z-index: 30;
}
2、动态过滤数据(结合 @if
)
只处理符合条件的元素:
$sizes: 8, 12, 16, 24;
@each $size in $sizes {
@if $size > 12 {
.icon-#{$size} {
width: #{$size}px;
height: #{$size}px;
}
}
}
编译后:
.icon-16 {
width: 16px;
height: 16px;
}
.icon-24 {
width: 24px;
height: 24px;
}
3、嵌套遍历生成工具类
生成多方向的边距和填充工具类:
$directions: (
"t": "top",
"b": "bottom",
"l": "left",
"r": "right",
);
$spacings: (0, 4, 8, 16);
@each $abbr, $dir in $directions {
@each $size in $spacings {
.m#{$abbr}-#{$size} {
margin-#{$dir}: #{$size}px;
}
.p#{$abbr}-#{$size} {
padding-#{$dir}: #{$size}px;
}
}
}
编译后:
.mt-0 {
margin-top: 0px;
}
.pt-0 {
padding-top: 0px;
}
.mt-4 {
margin-top: 4px;
}
.pt-4 {
padding-top: 4px;
}
/* ...其他方向 */
4、与混入(Mixin)结合
动态生成主题样式:
@mixin generate-theme($themes) {
@each $name, $color in $themes {
.theme-#{$name} {
background: $color;
color: lighten($color, 40%);
}
}
}
$theme-colors: (
"primary": blue,
"success": green,
);
@include generate-theme($theme-colors);
编译后:
.theme-primary {
background: blue;
color: #b3d1ff;
}
.theme-success {
background: green;
color: #b3ffb3;
}
五、注意事项
避免过度嵌套:嵌套多层
@each
会导致生成的 CSS 体积过大,影响性能。优先使用映射(Map):映射比嵌套列表更易读和维护:
// 推荐:清晰映射结构 $breakpoints: ( "sm": 576px, "md": 768px, ); // 不推荐:嵌套列表可读性差 $breakpoints: "sm" 576px, "md" 768px;
变量作用域:循环内定义的变量仅在当前循环体中有效,不会污染外部作用域。
六、@each
与其他循环指令对比
指令 | 适用场景 | 特点 | 示例 |
---|---|---|---|
@each | 遍历列表或映射中的元素 | 适合处理集合数据(如颜色列表) | 主题色、图标类生成 |
@for | 按数字范围循环(如 1 到 5) | 简洁,适合固定次数迭代 | 栅格系统、序列化类名 |
@while | 动态终止条件的复杂循环逻辑 | 灵活性高,需手动控制终止条件 | 根据变量动态生成类名 |
七、实际应用场景
1、主题系统开发
$themes: (
"light": (
bg: white,
text: black,
),
"dark": (
bg: black,
text: white,
),
);
@each $name, $colors in $themes {
.theme-#{$name} {
background: map-get($colors, bg);
color: map-get($colors, text);
}
}
2、生成图标类
$icons: "home", "user", "settings";
@each $icon in $icons {
.icon-#{$icon} {
background-image: url("/icons/#{$icon}.svg");
}
}
3、响应式工具类
$breakpoints: (
"sm": 576px,
"md": 768px,
);
@each $name, $size in $breakpoints {
@media (min-width: $size) {
.text-#{$name} {
font-size: $size * 0.02;
}
}
}
八、最佳实践
用映射管理配置数据 集中管理颜色、尺寸等配置,提升可维护性。
拆分复杂逻辑 若遍历逻辑复杂,将其拆分到混合宏或函数中。
避免生成冗余代码 结合
@if
过滤不必要的数据,减少 CSS 体积。注释说明意图 对复杂遍历逻辑添加注释,解释数据结构和用途。
九、总结
核心优势 | 典型场景 | 关键技巧 |
---|---|---|
简化集合数据处理 | 主题系统、工具类生成 | 结合 map-get() 和嵌套遍历 |
动态生成样式 | 响应式设计、图标类生成 | 与混合宏结合封装逻辑 |
提升代码可维护性 | 配置集中管理、减少重复代码 | 优先使用映射替代嵌套列表 |
通过合理使用 @each
,可以显著提升 Sass 代码的动态性和可维护性,尤其适合处理需要批量生成相似样式的场景。
更新日志
2025/8/24 08:17
查看所有更新日志
e7112
-1于