sass嵌套

tech2022-12-26  110

sass嵌套

The title of this post may be surprising to some of you. If you are a Sass veteran, you may remember the days (pre-Ruby-Sass-3.3) of using lists of lists to emulate nested arrays of data. (Ruby) Sass 3.3 added a new data type called maps. Lists of lists could hold complex data in a nested format, but without key-value pairing. Maps added key-value pairs and let us create arrays of data.

这篇文章的标题可能会让您有些惊讶。 如果您是Sass的资深人士,您可能还记得使用列表列表模拟嵌套数据数组的日子(在Ruby-Sass-3.3之前)。 (Ruby)Sass 3.3添加了一种称为maps的新数据类型。 列表列表可以嵌套格式存储复杂数据,但是没有键值对。 Maps添加了键值对,并让我们创建了数据数组。

With the advent of maps, many of us Sass users started putting everything into maps (and for good reason!). All your breakpoint widths, color values, grid layouts, type scales and other responsive typography details can go into maps!

随着地图的出现,我们许多Sass用户开始将所有内容都放入地图中(并且有充分的理由!)。 您所有的断点宽度 , 颜色值 , 网格布局 , 类型比例和其他响应式排版细节都可以放入地图!

Now that Sass has maps with key-value pairs, is there a good reason to use a list of lists? One theoretical reason would be backwards-compatibility: if your Sass might be maintained by a developer with an older version installed, lists will help them. In practice, however, Sass versions are often controlled by a package.json or other project config, and the Ruby gem can be updated with just one command (gem update sass).

现在,Sass拥有带有键-值对的映射,是否有充分的理由使用列表列表? 一个理论上的原因是向后兼容:如果您的Sass可以由安装了旧版本的开发人员维护,则列表将为他们提供帮助。 但是实际上,Sass版本通常由package.json或其他项目配置控制,并且Ruby gem可以仅使用一个命令( gem update sass )进行gem update sass 。

A more practical reason that you might choose to use nested lists instead of a map is typing less. Let’s compare a map and a nested list to see how they compare in their own syntax, and in how we’d loop through them.

您可能选择使用嵌套列表而不是地图的更实际的原因是键入的次数更少。 让我们比较一下地图和嵌套列表,看看它们如何以自己的语法进行比较,以及如何遍历它们。

比较语法 (Comparing Syntax)

For our example, let’s create a data structure that controls responsive typography. It will store four breakpoints (well, one is the default smallest view). For each breakpoint, we’ll store min-width, max-width, a base font-size, and a base line-height.

对于我们的示例,让我们创建一个控制响应式排版的数据结构。 它会存储四个断点(嗯,一个是默认的最小视图)。 对于每个断点,我们将存储min-width , max-width ,基本font-size和base line-height 。

复杂地图语法 (Complex Map Syntax)

Here’s how we’d store that data in a map. One large map will contain four keys (breakpoint labels) whose values are maps of the variables we need to store and use. In a readable format like this, we’ve got a little more than 450 characters and 26 lines.

这是我们将数据存储在地图中的方式。 一个大的映射将包含四个键(断点标签),其值是我们需要存储和使用的变量的映射。 在这样的可读格式中,我们有450多个字符和26行。

$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 ) );

嵌套列表语法 (Nested List Syntax)

The nested list for storing this same data is much shorter. We no longer have keys attached to our data however, so we have to rely on looping through it, or calling it with nth() functions. That said, it’s much shorter than the map: less than 180 characters and only 6 lines.

用于存储相同数据的嵌套列表要短得多。 但是,我们不再将键附加到数据上,因此我们必须依靠循环遍历数据或使用nth()函数进行调用 。 也就是说,它比地图短得多:少于180个字符,只有6行。

$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) );

比较循环 (Comparing Loops)

When it comes to typing out our data structure, typing lists takes about a third of the time of typing a map. If we need to loop through those values, however, how does that compare?

在输入数据结构时,输入列表大约需要输入地图的三分之一。 但是,如果我们需要遍历这些值,该如何比较?

复杂地图循环 (Complex Map Loop)

We can use the following code to loop through the top level items in this map:

我们可以使用以下代码遍历此地图中的顶级项目:

@each $label, $map in $breakpoint-map {}

The two variables at the beginning of this line ($label and $map) are dynamically assigned as the loop iterates through the data in the map. Each top-level piece of data has two components: a key and a value. We’re assigning the key to $label and the value (which is a nested map) to $map. Inside this loop, we can use the variables $label and $map and they’ll automatically represent the key and value of the current entry.

当循环迭代映射中的数据时,动态分配此行开头的两个变量( $label和$map )。 每个顶级数据都有两个组成部分:键和值。 我们将键分配给$label ,并将值(这是一个嵌套映射)分配给$map 。 在此循环中,我们可以使用变量$label和$map ,它们将自动表示当前条目的键和值。

That loop will iterate four times, once for each nested map. To get useful data out of the nested map, however, we’ll need to use the map-get() function. This function takes two parameters – the name of the map and the name of the desired key – and returns the value associated with that key. It’s the Sass equivalent to PHP’s $array['key'] and $object->key or JavaScript’s object.key syntax.

该循环将迭代四次,每个嵌套地图一次。 但是,要从嵌套地图中获取有用的数据,我们需要使用map-get()函数 。 此函数采用两个参数-映射名称和所需键的名称-并返回与该键关联的值。 它与PHP的$array['key']和$object->key或JavaScript的object.key语法object.key 。

To iterate through all the sub-maps with @each and assign their values to useful variables with map-get(), we end up with a 6-line, 220-character loop.

要使用@each遍历所有子映射,并使用map-get()将其值分配给有用的变量,我们最终得到了一个6行,220个字符的循环。

@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); }

嵌套列表循环 (Nested List Loop)

Nested lists really make looping efficient. With maps, we had to assign a map to a dynamic loop variable and then use map-get() to assign all its values to variables, but with lists, we can quickly assign all values to variables.

嵌套列表确实使循环有效。 对于映射,我们必须将映射分配给动态循环变量,然后使用map-get()将其所有值分配给变量,但是对于列表,我们可以快速将所有值分配给变量。

Since each item in the top-level list has the same five values in the same order, we can instantly assign each of those to a dynamic variable to use inside our loop. With those variables, we don’t need to use map-get() to assign sub-values to usable variables. The loop we need for nested lists is only two lines and less than 100 characters.

由于顶级列表中的每个项目都以相同的顺序具有相同的五个值,因此我们可以立即将每个值分配给一个动态变量,以在循环中使用。 使用这些变量,我们无需使用map-get()将子值分配给可用变量。 嵌套列表所需的循环只有两行,并且少于100个字符。

@each $label, $min-width, $max-width, $base-font, $vertical-rhythm in $breakpoint-list { }

嵌套列表警告 (Nested List Warnings)

Nested lists are a major developer performance win: overall, you’ll probably type less than half as much as you’d type if you were using a map. However, there’s a reason maps were added to Sass: they provide a feature lists don’t: key-value mapping.

嵌套列表是开发人员获得性能的主要胜利:总体而言,如果使用地图,则键入的内容可能少于键入内容的一半。 但是,将映射添加到Sass是有原因的:它们没有提供功能列表:键值映射。

缺失值 (Missing Values)

If you’re going to rely on nested lists, you must be absolutely certain you know how many items each list will hold and what order they’ll be in. Let’s look at what would happen in our example above if we left out an item in one of our lists:

如果您要依赖嵌套列表,则必须绝对确定您知道每个列表将容纳多少个项目以及它们将处于什么顺序。让我们看看如果忽略一个项目,在上面的示例中会发生什么在我们的清单之一中:

$breakpoint-list: ( (small, null, 479px, 16px, 1.3), (medium, 480px, 959px, 18px, 1.414), (large, 960px, 1099px, 18px, 1.5), (xlarge, 1100px, 21px, 1.618) ); p { @each $label, $min-width, $max-width, $base-font, $vertical-rhythm in $breakpoint-list { @if $min-width { @include breakpoint( $min-width ) { font-size: $base-font; line-height: $vertical-rhythm; } } @else { font-size: $base-font; line-height: $vertical-rhythm; } } }

If we try running that code, the last list will break. It will correctly assign ‘xlarge’ to $label and ‘1100px’ to $min-width, but then it will assign ’21px’ to $max-width and ‘1.618’ to $base-font, leaving $vertical-rhythm blank. As a result, we end up with an invalid font-size declaration and a missing line-height property in the last breakpoint. Additionally, Sass doesn’t report an error for this, so we’d have no idea if things worked out or not. If we had tried using the max-width for a media query, we would have ended up with the font-size value (just 21px) – that would be a pretty useless max-width, I think!

如果我们尝试运行该代码,则最后一个列表将中断。 它将正确地将'xlarge'分配给$label并将'1100px'分配给$min-width ,但是随后它将将'21px'分配给$max-width并将'1.618'分配给$base-font ,而将$vertical-rhythm留$vertical-rhythm空白。 结果,我们在最后一个断点处得到了无效的font-size声明和缺少的line-height属性。 此外,Sass不会为此报告错误,因此我们不知道事情是否解决。 如果我们尝试使用max-width进行媒体查询,我们最终将得到font-size值(仅为21px )–我认为这将是一个非常无用的max-width!

If we’d used maps instead, the map-get() function would’ve given us what we needed even if one of the values were missing. That’s our trade-off: what we gain in simplicity and speed with lists, we lose in specificity and error-proofing with maps.

如果我们改用地图,则即使缺少其中一个值, map-get()函数也会提供所需的信息。 那是我们的权衡:通过列表,我们在简单性和速度上获得了好处,而在地图上却失去了特异性和防错能力。

查询特定列表 (Querying a Specific List)

A related concern with using nested lists is querying for a specific list. Since maps have keys, you can quickly access any of the sub-maps with map-get():

使用嵌套列表的一个相关问题是查询特定列表。 由于地图具有键,因此您可以使用map-get()快速访问任何子map-get() :

$medium-map: map-get($maps, medium);

To get the data from the medium list in the nested lists, we need a more complex function:

为了从嵌套列表中的medium列表中获取数据,我们需要一个更复杂的函数:

@function get-list($label) { @each $list in $breakpoint-list { @if nth($list, 1) == $label { @return $list; } } @return null; } $medium-list: get-list(medium);

That function loops through all the lists in $breakpoint-list, checks the first value for the label we want, and returns the list if it finds a match. If it gets to the end of the @each loop without finding a match, it’ll return null. It’s basically a quick homemade interpretation of map-get() for lists that use the first value as a faux key.

该函数遍历$breakpoint-list所有$breakpoint-list ,检查所需标签的第一个值,如果找到匹配项,则返回列表。 如果到达@each循环的末尾而没有找到匹配项,它将返回null 。 对于使用第一个值作为伪键的列表,这基本上是对map-get()的快速自制解释。

缺少地图功能 (Missing Map Functions)

Sass has quite a few useful functions for dealing with maps: those same functions don’t exist for nested lists. For example, you can use map-merge() to add additional key-value pairs to a map. Using map-merge() with shared keys will update the value for shared keys. You can add a new list using join() or append(), but faking the update feature of map-merge() would require another custom Sass function.

Sass有很多处理地图的有用功能:嵌套列表不存在相同的功能。 例如,您可以使用map-merge()将其他键值对添加到地图。 将map-merge()与共享密钥一起使用将更新共享密钥的值。 您可以使用join()或append()添加新列表,但伪造map-merge()的更新功能将需要另一个自定义Sass函数。

Another useful map function is map-has-key(). This function is useful for validating any custom function that relies on map-get(). There’s no comparable function for lists, however.

另一个有用的地图函数是map-has-key() 。 该函数对于验证依赖于map-get()任何自定义函数很有用。 但是,列表没有类似的功能。

You can use SassyLists to mimic map functions with lists. (This library provided these functions before Sass added map support.)

您可以使用SassyLists模仿带有列表的地图功能。 (在Sass添加地图支持之前,该库提供了这些功能。)

结论 (Conclusion)

Maps are more powerful than lists because of they use key-value pairs. The additional Sass map functions provide useful ways to find data and validate map values.

映射比列表更强大,因为它们使用键值对。 附加的Sass映射功能提供了查找数据和验证映射值的有用方法。

Nested Sass lists can be quicker to write and maintain, but they’re probably not as well-suited for error-checking or detailed querying as maps. Most of the time, I believe maps are the better option, in spite of the increased verbosity. For smaller chunks of code and single-use loops, I’ll occasionally use a nested list, but maps work better for project-wide settings and data storage.

嵌套的Sass列表可以更快地编写和维护,但它们可能不像地图那样不适合进行错误检查或详细查询。 我相信大多数时候,尽管详细程度有所提高,但地图是更好的选择。 对于较小的代码块和一次性循环,我偶尔会使用嵌套列表,但是地图在项目范围内的设置和数据存储中效果更好。

Have you compared maps and nested lists in any of your work, or refactored code to prefer one over the other? Share your experience in the comments!

您是否在任何工作中比较了地图和嵌套列表,还是在重构代码中优先使用一个? 在评论中分享您的经验!

You can see the code used for this tutorial in this Sassmeister gist.

您可以在Sassmeister要点中查看用于本教程的代码。

翻译自: https://www.sitepoint.com/sass-maps-vs-nested-lists/

sass嵌套

最新回复(0)