核心要点
map-get()
函数仍然可以提供所需的值。本文标题可能会让一些人感到意外。如果您是Sass老手,您可能还记得使用列表的列表来模拟嵌套数据数组的日子(在Ruby-Sass-3.3之前)。(Ruby) Sass 3.3添加了一种名为映射的新数据类型。列表的列表可以以嵌套格式保存复杂数据,但没有键值配对。映射添加了键值对,并让我们创建数据数组。
随着映射的出现,我们许多Sass用户开始将所有内容都放入映射中(并且有充分的理由!)。所有断点宽度、颜色值、网格布局、类型比例和其他响应式排版细节都可以放入映射中!
现在Sass有了键值对映射,还有使用列表的列表的好理由吗?一个理论上的原因是向后兼容性:如果您的Sass可能由安装了较旧版本的开发人员维护,列表将帮助他们。然而,在实践中,Sass版本通常由package.json
或其他项目配置控制,并且Ruby gem只需一个命令即可更新(gem update sass
)。
您可能选择使用嵌套列表而不是映射的一个更实际的原因是输入较少。让我们比较一下映射和嵌套列表,看看它们在各自语法和循环遍历方式上的比较。
语法比较
在我们的示例中,让我们创建一个控制响应式排版的 数据结构。它将存储四个断点(好吧,一个是最小的默认视图)。对于每个断点,我们将存储最小宽度、最大宽度、基本字体大小和基本行高。
以下是我们将数据存储在映射中的方法。一个大型映射将包含四个键(断点标签),其值是我们需要存储和使用的变量的映射。以这种可读的格式,我们有超过450个字符和26行。
<code>$breakpoint-map: ( small: ( min-width: null, max-width: 479px, base-font: 16px, vertical-rhythm: 1.3 ), medium: ( min-width: 480px, max-width: 959px, base-font: 18px, vertical-rhythm: 1.414 ), large: ( min-width: 960px, max-width: 1099px, base-font: 18px, vertical-rhythm: 1.5 ), xlarge: ( min-width: 1100px, max-width: null, base-font: 21px, vertical-rhythm: 1.618 ) );</code>
存储相同数据的嵌套列表要短得多。但是,我们不再将键附加到数据,因此我们必须依赖于循环遍历它或使用nth()
函数调用它。也就是说,它比映射短得多:少于180个字符,只有6行。
<code>$breakpoint-list: ( (small, null, 479px, 16px, 1.3), (medium, 480px, 959px, 18px, 1.414), (large, 960px, 1099px, 18px, 1.5), (xlarge, 1100px, null, 21px, 1.618) );</code>
循环比较
在编写数据结构时,编写列表大约只需要编写映射时间的三分之一。但是,如果我们需要循环遍历这些值,那又如何比较呢?
我们可以使用以下代码循环遍历此映射中的顶级项目:
<code>@each $label, $map in $breakpoint-map {}</code>
此行开头的两个变量($label
和$map
)在循环迭代映射中的数据时动态分配。每个顶级数据块有两个组成部分:键和值。我们将键分配给$label
,并将值(这是一个嵌套映射)分配给$map
。在这个循环中,我们可以使用变量$label
和$map
,它们将自动表示当前条目的键和值。
该循环将迭代四次,每次迭代一个嵌套映射。但是,要从嵌套映射中获取有用的数据,我们需要使用map-get()
函数。此函数采用两个参数——映射的名称和所需键的名称——并返回与该键关联的值。它是Sass中PHP的$array['key']
和$object->key
或JavaScript的object.key
语法的等效项。
要使用@each
迭代所有子映射并将它们的值使用map-get()
分配给有用的变量,我们最终得到一个6行、220个字符的循环。
<code>@each $label, $map in $breakpoint-map { $min-width: map-get($map, min-width); $max-width: map-get($map, max-width); $base-font: map-get($map, base-font); $vertical-rhythm: map-get($map, vertical-rhythm); }</code>
嵌套列表确实使循环效率更高。对于映射,我们必须将映射分配给动态循环变量,然后使用map-get()
将所有值分配给变量,但是对于列表,我们可以快速地将所有值分配给变量。
由于顶级列表中的每个项目都按相同顺序具有相同的五个值,因此我们可以立即将每个值分配给动态变量以在循环中使用。使用这些变量,我们不需要使用map-get()
将子值分配给可用的变量。我们需要的嵌套列表循环只有两行,少于100个字符。
<code>@each $label, $min-width, $max-width, $base-font, $vertical-rhythm in $breakpoint-list { }</code>
嵌套列表警告
嵌套列表是主要的开发人员性能优势:总的来说,您输入的内容可能不到使用映射时的一半。但是,添加映射到Sass是有原因的:它们提供列表不具备的功能:键值映射。
如果您要依赖嵌套列表,您必须绝对确定您知道每个列表将包含多少个项目以及它们的顺序。让我们看看如果我们在列表中遗漏了一个项目,上面的示例会发生什么:
<code>$breakpoint-map: ( small: ( min-width: null, max-width: 479px, base-font: 16px, vertical-rhythm: 1.3 ), medium: ( min-width: 480px, max-width: 959px, base-font: 18px, vertical-rhythm: 1.414 ), large: ( min-width: 960px, max-width: 1099px, base-font: 18px, vertical-rhythm: 1.5 ), xlarge: ( min-width: 1100px, max-width: null, base-font: 21px, vertical-rhythm: 1.618 ) );</code>
如果我们尝试运行该代码,最后一个列表将中断。它将正确地将“xlarge”分配给$label
并将“1100px”分配给$min-width
,但随后它将“21px”分配给$max-width
并将“1.618”分配给$base-font
,使$vertical-rhythm
为空。结果,我们在最后一个断点中得到一个无效的字体大小声明和一个缺少的行高属性。此外,Sass不会为此报告错误,因此我们不知道事情是否成功。如果我们尝试将最大宽度用于媒体查询,我们将最终得到字体大小值(只有21px)——我认为这将是一个非常无用的最大宽度!
如果我们改用映射,即使缺少一个值,map-get()
函数也会给我们提供我们需要的东西。这就是我们的权衡:我们在列表中获得的简单性和速度,我们在映射中失去了特异性和防错性。
使用嵌套列表的另一个相关问题是查询特定列表。由于映射具有键,因此您可以使用map-get()
快速访问任何子映射:
<code>$breakpoint-list: ( (small, null, 479px, 16px, 1.3), (medium, 480px, 959px, 18px, 1.414), (large, 960px, 1099px, 18px, 1.5), (xlarge, 1100px, null, 21px, 1.618) );</code>
要从嵌套列表中获取中等列表的数据,我们需要一个更复杂的函数:
<code>@each $label, $map in $breakpoint-map {}</code>
该函数循环遍历$breakpoint-list
中的所有列表,检查我们想要标签的第一个值,如果找到匹配项则返回列表。如果在没有找到匹配项的情况下到达@each
循环的末尾,它将返回null。它基本上是列表的map-get()
的快速自制解释,它使用第一个值作为伪键。
Sass有很多有用的函数可以处理映射:嵌套列表不存在相同的函数。例如,您可以使用map-merge()
向映射添加其他键值对。使用具有共享键的map-merge()
将更新共享键的值。您可以使用join()
或append()
添加一个新列表,但是模拟map-merge()
的更新功能将需要另一个自定义Sass函数。
另一个有用的映射函数是map-has-key()
。此函数对于验证依赖于map-get()
的任何自定义函数非常有用。但是,列表没有可比的函数。
您可以使用SassyLists模拟列表的映射函数。(在Sass添加映射支持之前,此库提供了这些函数。)
结论
由于映射使用键值对,因此它们比列表更强大。附加的Sass映射函数提供了查找数据和验证映射值的实用方法。
嵌套Sass列表编写和维护起来可能更快,但它们可能不如映射那样适合错误检查或详细查询。大多数情况下,我认为映射是更好的选择,尽管冗长性有所增加。对于较小的代码块和单次使用循环,我偶尔会使用嵌套列表,但映射更适合项目范围的设置和数据存储。
您是否在您的任何工作中比较了映射和嵌套列表,或者重构了代码以优先使用一个而不是另一个?在评论中分享您的经验!
您可以在此Sassmeister gist中看到本教程中使用的代码。
Sass映射与嵌套列表的常见问题解答 (FAQ)
Sass映射和嵌套列表都是Sass预处理器中的强大工具,但它们有明显的区别。Sass映射类似于其他编程语言中的关联数组,其中每个值都与一个唯一的键相关联。这使得检索、更新和操作数据变得容易。另一方面,嵌套列表是一系列值,类似于JavaScript中的数组。当您需要存储和迭代一系列值时,它们最适合使用,但它们缺乏映射提供的直接访问特定值的功能。
要使用Sass映射,您首先需要使用一对括号定义一个映射,每个键值对用冒号分隔。例如,$map: (key1: value1, key2: value2)
。然后,您可以使用map-get
函数访问映射中的值,如下所示:map-get($map, key1)
。
是的,您可以像嵌套列表一样嵌套Sass映射。当您想要将相关数据组合在一起时,这尤其有用。要访问嵌套映射中的值,您需要使用两次map-get
函数:map-get(map-get($map, key1), key2)
。
您可以使用@each
指令迭代Sass映射。@each
指令采用两个变量:键和值。这是一个示例:@each $key, $value in $map { … }
。
Sass映射比嵌套列表具有几个优点。它们允许直接访问特定值,使您的代码更高效且更易于阅读。它们还提供用于操作映射的内置函数,例如添加、删除和更新键值对。
是的,您可以使用map-from-list
函数将嵌套列表转换为Sass映射。此函数采用一对列表并返回一个映射,其中每一对都是映射中的键值对。
要在Sass中使用嵌套列表,您首先需要使用一对括号定义一个列表,每个值用空格或逗号分隔。例如,$list: (value1, value2, value3)
。然后,您可以使用nth
函数访问列表中的值,如下所示:nth($list, 1)
。
是的,您可以同时使用Sass映射和嵌套列表。例如,您可以使用映射来存储一系列列表,反之亦然。这对于组织复杂的数据结构很有用。
虽然Sass映射和嵌套列表是强大的工具,但它们确实有一些限制。例如,Sass映射不能有重复的键,并且映射中键的顺序不能保证。同样,如果嵌套列表变得太大或太复杂,则可能难以管理。
使用Sass映射或嵌套列表的选择取决于您的具体需求。如果您需要直接访问特定值并能够操作数据,则Sass映射可能是最佳选择。如果您只需要存储和迭代一系列值,则嵌套列表就足够了。
以上是SASS地图与嵌套列表的详细内容。更多信息请关注PHP中文网其他相关文章!