理解Sass的list

发布于 大漠

Sass中的List是一个让人可爱又可恨的东西。主要是他的语法太宽松,你几乎可以做任何你想做的事情。如果要想更好的使用好Sass语言中的List功能,我们就必须的深入了解他。Hugo写了几篇教程,其深入的培析了Sass的List功能,以及其使用方法。

除了这向篇文章,在互联网上很难找到有关于Sass的List更好教程了。而在Sass的社区中对List的功能讨论也是相当的激烈。这些天我也一直在阅读这几篇文章,想让自己能更好的理解Sass中的List功能。今天根据这几篇文章,对List功能的介绍做了一些翻译与整理。

创建一个Sass的list

首要的事情就是创建List。虽然在Sass中创建一个list可能会非常棘手,但事实上呢?Sass对于变量类型并不是非常严格,可以像理解Javascript语言一样,Sass也是一种弱类型语言。这样就意味着,处理一个列表你就可以像是在处理一个字符串,或者说是一个字符串列表功能。

Sass对于变量类型不是非常严格

在Sass中,有两种方法可以用来初始化一个的变量(这也可以被视为一个列表):

$a:();
$b:unquote(" ");//注意,冒号之间有一个空格
$c:null;
$d:(null);

现在我们创建了四个变量,接着通过Sass的type-of()函数来检测这些变量的类型:

type-of($a) => list
type-of($b) => string
type-of($c) => null
type-of($d) => null

接下来,使用length()函数来检测一下每个变量的长度:

length($a) => 0
length($b) => 1
length($c) => 1
length($d) => 1

$a的长度是0,这是我们能预想到的,因为他是一个空列表。$b的长度是1,因为他是一个字符串,然而$c$d都是null变量(空变量),令人想不通的是,他们的长度也是1

虽然$a$c($d)都可以用来初始化一个List(甚至是unquote(""),注,冒号之间没有任何空格),但前面简单的长度测试告诉我们,他们其实并不是完全一样的。当然如果你喜欢,你可以使用他们来初始化Sass的一个列表,但大家必须要记住,他们之间是不一样的。

()null的区别

null等同于(null)或者unquote("")他们都是用来做为列表的第一个列表项,大多数情况之下,用他们来对Sass的列表进行初始化,但是和()并不完全一样,接下来通过几个简单的测试来说明()null的区别。

假设有两个变量:

$a:();
$b:null;

使用type-of()函数测试出变量的类型:

type-of($a) => list
type-of($b) => null

使用length()函数输出变量的长度值:

length($a) => 0
length($b) => 1

变量$a$b都是一个列表,通过nth()函数来检测出第一个列表项:

nth($a,1) => throws error
nth($b,1) => 

由于$a长度是0,在nth()函数检出其第一个列表项,在Sass编译的时候将会报错,而$b第一项刚好是空,那么在nth()函数检出其第一个列表项是一个空,没有任何东西。

接下来使用append()函数为每个列表添加一个列表项test

$a: append($a,"test");
$b: append($b,"test");

再次检测其长度:

length($a) => 1
length($b) => 2

使用index()函数来检测“test”列表项在列表中各处什么位置:

index($a,"test") => 1
index($b,"test") => 2

使用nth()函数,再次检出列表的第一个列表项,这个时候又变了:

nth($a,1) => test
nth($b,1) => 

我想这几个函数对$a$b变量的操作,一路下来,您应该很清楚的知道()null的不同之处了吧。

Sass的List

Sass的list非常类似于JavaScript语言中的数组。你可以通过下面的方式来初始化一个Sass的List:

$list:();

当然,你也还可以使用$list:null或者$list:unquote(""),但你要注意一下他们之间的不同。不管使用哪种方法,我们先来看一个简单的Sass列表:

$list:(#b4d455,42,"awesome");

前面也说过,Sass语法非常宽松,这也让 list在Sass中使用变得更加的复杂。我们一个一个来看。

列表的分隔符

在Sass的列表中,你可以使用空格符或者逗号作为列表项与列表项之间的分隔符。事实上,我更喜欢使用逗号(,)用来做为列表的分隔符。在JavaScriptPHP这些语言中,都是用逗号作为数组的分隔符。

$list-space: "item-1" "item-2" "item-3";
$list-space: "item-1","item-2","item-3";

注:和CSS一样,只要没有特殊字符,列表项的双引号是可以省略的。所以$list: item-1,item-2,item-3;是有效的。

列表的嵌套

Sass的List就像JavaScript或者其他的程序语言一样,对列表的嵌套层级并没有限制,可以根据自己的需求对列表进行嵌套。Sass的嵌套主要有两种方式,一种是嵌套的列表子级列表项是以逗号分隔,那么在列表中需要用括号来分隔;另一种嵌套的列表子级用空格分隔,那么在列表中可以使用逗号来分隔。

/* Nested lists with braces and same separator */
$list: ( 
        ("item-1.1", "item-1.2", "item-1.3"), 
        ("item-2.1", "item-2.2", "item-2.3"),
        ("item-3.1", "item-3.2", "item-3.3")
       );

/* Nested lists without braces using different separators to distinguish levels */
$list: "item-1.1" "item-1.2" "item-1.3", 
       "item-2.1" "item-2.2" "item-2.3",
       "item-3.1" "item-3.2" "item-3.3";

你可以使用括号

正如你前面看到的示例一样,在Sass中,你可以不用括号定义一个非空的列表。这主要是因为大多数人的想法相反,在Sass中括号不是用来创建列表(除非是空的列表),而是用来做为分隔符的。

事实上,在Sass中没有人会强迫您使用括号来创建一个列表,如果你喜欢,完全可以使用逗号来区别。说实话,我就经常使用逗号来创建一个列表:

$list: "item-1", "item-2", "item-3";

注:这是一个理论。我注意到括号都不只是一个列表项分组。当你操作的一个列表有四五层的嵌套时,括号绝对不是可选的。这样会让列表变得太复杂了。

操作一个五层以上的嵌套列表是一件痛苦而又麻烦的事情

列表的索引值

Sass中的列表索引值和JavaSctript数组中的索引值不一样,他是从1开始,而不是从0开始。一旦你开始使用Sass列表,这个问题也是最容易出错的。

nth($list,0) => throws error
nth($list,1) => item-1

每个值都是一个列表

在Sass中每一个值都可以是一个列表。字符串、数值、布尔值或者任何变量。而且可以通过Sass的List函数来检测出一些值。

我们来看一个简单的例子:

$variable: "Sass is awesome";
$variable2: Sass is awesome;

上面两个变量值仅仅就是一个有引号,一个没有引号。

使用type-of()函数检测出他们的类型:

>> type-of($variable)
"string"
>> type-of($variable2)
"list"
>> 

使用length()函数检测出他们的长度:

>> length($variable)
1
>> length($variable2)
3

在用nth()函数来检测输出内容:

>> nth($variable,1)
"Sass is awesome"
>> nth($variable2,1)
"Sass"
>> 

这里变动一下,来索引第二个值:

>> nth($variable,2)
SyntaxError: List index is 2 but list is only 1 item long for `nth'
>> nth($variable2,2)
"is"

所在大家在使用的时候当心了,有引号的时候会当为一个字符串,当然他也是一个只有一个列表项的列表,而删除引号会被视为有三个列表项的列表。

可以使用空格或逗号分隔列表项

在Sass的列表中,使用空格和逗号都可以用来分隔列表项,这两者都是完全有效的。我敢肯定你更喜欢使用逗号来分隔列表项,因为在JavaScriptPHP等程序中的数组,逗号是一个标准的分离器。如果你喜欢也可以用空格分隔。

$list: #fff 42 "awesome";
$list: #fff,42,"awesome";

你也可以使用逗号和空格分隔符混用,此时用来区别列表的嵌套。比如说你的一级列表中使用逗号来分隔列表项,而且他里面还嵌套了一个二级列表,那么二级列表可以使用空格来分隔。在下面的示例当中,第三个值是一个空格分隔的列表:

$list:  #b4d455, 42, "awesome" "interesting" "free";

综合上述,在任何情况之下,定义你的列表时,你应该注意以下几点:

  • 使用括号进行列表嵌套;
  • 使用逗号分隔列表项;
  • 给字符串添加引号;
  • 列表嵌套不要超过五层;
  • 初始化列表建议使用(),不使用null;

这些细节都将帮助您节省更多的时间,请相信我。

列表函数

在Sass中,给列表提供了一系列的函数操作。在《Sass函数》一文中,对列表的函数进行过详细介绍,感兴趣的可以看看。此处将Sass函数做一个汇总。

  • length($list):返回$list长度(如果不是list,返回1)
  • nth($list,$index):返回$list中第$index列表项值(如果索引值不在列表范围内,将会报错)
  • index($list,$value):返回$value$list中的位置
  • append($list,$value[,$separator]):使用$separator分隔符将$value列表项添加到$list最后(如果没有显式指定$separator分隔符,会以当前分隔符分隔)
  • join($list-1,$list-2[,$separator]):使用$separator分隔符将$list-2附加到$list-1(如果没有显式指定分隔符,将对$list-1中的分隔符)
  • zip(*$lists):将多个$list组合在一起成为一个多维列表。如果列表源长度并不是所有都相同,结果列表长度将以最短的一个为准
  • reject($list,$value):这是Compass中的一个函数,将$value值从$list中删除
  • compact(*$args):Compass函数,返回一个删除非真值的新列表

Sass列表应用

Sass中的list是一个很有趣的东西,但也是个很复杂的东西。前面都是一些理论化,接下来通过一个例子的使用来介绍list

比如说一个扩展选择器,如:

.home .nav-home,
.about .nav-about,
.products .nav-products,
.contact .nav-contact

这些选择器都是基于列表的关键值生成:

$pages: home,about,products,contact;

根据这个列表,有三种方法可以生成这样的选择器,我们可以一个一个来看。

首先我们创建一个测试例子:

$pages: home,about,products,contact;
$selector:();
@each $item in $pages {
    //我们创建$selector
}
#{$selector}{
    //样式写在这里
}

长而复杂的方法

这是我两星期前使用的一个方法,它可以运行,但它需要一个额外的条件来处理逗号。如:

@each $item in $pages{
    $selector: $selector unquote(".#{$item} .nav-#{$item}");
    @if $item != nth($pages, length($pages)){
        $selector: $selector unquote(",");
    }
}

基本上给$selector添加了新的选择器,如果我们不处理列表的最后一项,我们需要添加一个逗号。

简洁的方法

这种方法是通过append()函数方法,将他们添加到一起。这也是最简单的方法。

@each $item in $pages{
    $selector: append($selector,unquote(".#{$item} .nav-#{$item}"),comma);  
}

我认为这是很简单的,我们将显示的使用逗号将选择器与前面的分隔开,并将此重新赋以给新的选择器$selector

隐式的方法

这种方法是最简单的,通过隐式的附加功能,将选择器合在一起,非常的简洁。

@each $item in $pages{
    $selector: $selector,unquote(".#{$item} .nav-#{$item}");    
}

自定义列表函数

前面介绍主要Sass中list的功能以及自带的处理list的函数,但很多更先进的列表处理到目前为止,Sass自身是无法处理的。

Hugo根据Sass的一些功能为list定义了一些高级的函数功能,用来处理Sass的list。并在《ADVANCED SASS LIST FUNCTIONS》一文中介绍了这些高级函数的功能,以及使用方法。接下来,我们也跟随此文了解和学习这些高级的列表函数。

我们来演示一个简单的函数。这里有两上小功能,就是定义两个函数用来获取列表中的第一个列表项和最后一个列表项的值。在很多时候我们都是通过nth()函数方式来获取:

nth($list,1);//获取列表中的第一个列表项
nth($list,length($list));//获取列表中的最后一个列表项

众所周知,Sass中的列表项索引号是从1开始,而length($list)可以获得一个列表的长度值,再配合nth()函数得到第一项和最后一项。那么我们可以换过一个角度来思考,将这两个分别封装成两个函数:

//定义first()函数,获取列表中的第一个列表项
@function first($list){
    @return nth($list,1);
}

//定义last()函数,获取列表中的最后一个列表项
@function last($list){
    @return nth($list,length($list));
}

例如我们一个颜色列表,我在页头header调用列表中第一个颜色,而在页脚footer调用列表中最后一个颜色,我们就可以这样来使用:

//定义颜色列表
$colors: green,blue,orange,yellow;

//调用列表中第一个颜色
.header {
    color: first($colors);//等同于nth($colors,1)
}

//调用列表中最后一个颜色
.footer{
    color: last($colors);//等同于nth($colors,length($colors))
}

转译出来的CSS

.header {
  color: green; 
}

.footer {
  color: yellow; 
}

很多时候列表只有一个列表项,此时first()last()函数获取的列表项将等同。

其它自定义的列表高级函数,如果你感兴趣,可以猛击这里

总结

本文主要根据Hugo写了几篇教程:《Create Striped Backgrounds With Gradients (and a Sass Mixin)》、《UNDERSTANDING SASS LISTS》、《ADVANCED SASS LIST FUNCTIONS》介绍了Sass中的list功能。

经过上面的阅读之后,你能轻松的创建一个列表,以及索引列表项的值,判断列表的长度等等功能。同时在项目中使用列表功能,让你更佳轻松的完成你的工作,并且还能让你的代码更佳的简洁。

最后非常感谢Hugo给我们带来这么优秀的Sass教程,希望大家在此文上有所获得。

如需转载,烦请注明出处:https://www.fedev.cn/preprocessor/understanding-sass-list.html

Yung-96 - Silver Metallic