对于一位程序员来说,对数组并不会陌生。但对于前端人员(像我这样不算前端的前端)对于数组,只是听过,看过,但不知道如何使用?然而在Sass3.3版本中开始引入一个新的数据类型maps,他长得跟数组非常的相似。但也让我极其的苦逼,因为我不懂数组呀,不知道如何下手开始使用Sass的map
功能。
通过阅读一些文章,觉得Sass的map
是Sass的强大的特性之一,能帮助我们做好更多的事情,比如说管理媒体查询的断点、管理z-index的值、管理颜色和管理排版等。接下来,我们一起来学习Sass的map
。
Sass的map
常常被称为数据地图,也有人称其为数组,因为他总是以key:value
成对的出现,但其更像是一个JSON数据。
{
"employees": [
{ "firstName":"John" , "lastName":"Doe" },
{ "firstName":"Anna" , "lastName":"Smith" },
{ "firstName":"Peter" , "lastName":"Jones" }
]
}
那么Sass的map
长得与JSON极其相似:
$map: (
$key1: value1,
$key2: value2,
$key3: value3
)
首先有一个类似于Sass的变量一样,用个$
加上命名空间来声明map
。后面紧接是一个小括号()
,将数据以key:value
的形式赋予,其中key
和value
是成对出现,并且每对之间使用逗号(,
)分隔,其中最后一组后面没有逗号。
其中键key
是用来查找相关联的值value
。使用map
可以很容易收集键的值和动态插入。我们来回忆一下,在Sass中常用下面的方式定义变量:
$default-color: #fff !default;
$primary-color: #22ae39 !default;
我们使用map
可以更好的进行管理:
$color: (
default: #fff,
primary: #22ae39
);
如果哪一天,你需要新增加颜色变量值,在map
中可以非常随意的添加:
$color: (
default: #fff,
primary: #22ae39,
negative: #d9534f
);
对于Sass的map
,还可以让map
嵌套map
。其实就是map
的某一个key
当成map
,里面可以继续放一对或者多对key:value
:
$map: (
key1: value1,
key2: (
key-1: value-1,
key-2: value-2,
),
key3: value3
);
map
的嵌套实用性也非常的强,大家可能有碰到过换皮肤的项目,可能每一套皮肤对应的颜色蛮多的,那么使用此功能来管理颜色的变量就非常的有条理性,便于维护与管理。你可以这样使用:
$theme-color: (
default: (
bgcolor: #fff,
text-color: #444,
link-color: #39f
),
primary:(
bgcolor: #000,
text-color:#fff,
link-color: #93f
),
negative: (
bgcolor: #f36,
text-color: #fefefe,
link-color: #d4e
)
);
在一些介绍map
的老教程中,你会看到这样的方式声明map
:
$map: (
key1 value1,
key2 value2,
key3 value3
);
或者:
$map:(
key1 value1,
key2 value2,
key3 (
key-1 value-1,
key-2 value-2
),
key4 value4
);
虽然也能编译出CSS,但建议不这样使用。
前面介绍了使用map
来管理变量,但要在Sass中获取变量,或者对map
做更多有意义的操作,我们必须借助于map
的函数功能。在Sass中map
自身带了七个函数:
map-get($map,$key)
:根据给定的key
值,返回map
中相关的值。map-merge($map1,$map2)
:将两个map
合并成一个新的map
。map-remove($map,$key)
:从map
中删除一个key
,返回一个新map
。map-keys($map)
:返回map
中所有的key
。map-values($map)
:返回map
中所有的value
。map-has-key($map,$key)
:根据给定的key
值判断map
是否有对应的value
值,如果有返回true
,否则返回false
。keywords($args)
:返回一个函数的参数,这个参数可以动态的设置key
和value
。接下来,我们先简单的了解这些函数的具体使用以及所具有的功能。
map-get($map,$key)
函数的作用是根据$key
参数,返回$key
在$map
中对应的value
值。如果$key
不存在$map
中,将返回null
值。此函数包括两个参数:
$map
:定义好的map
。$key
:需要遍历的key
。来看一个简单的示例,假设定义了一个$social-colors
的map
:
$social-colors: (
dribble: #ea4c89,
facebook: #3b5998,
github: #171515,
google: #db4437,
twitter: #55acee
);
假设要获取facebook
键值对应的值#3b5998
,我们就可以使用map-get()
函数来实现:
.btn-dribble{
color: map-get($social-colors,facebook);
}
编译出来的CSS:
.btn-dribble {
color: #3b5998;
}
我们来看另一种情况,假设$social-colors
这个map
没有$weibo
这个key
:
.btn-weibo{
font-size: 12px;
color: map-get($social-colors,weibo);
}
此时编译出来的是CSS:
.btn-weibo {
font-size: 12px;
}
从编译出来的CSS可以得知,如果$key
不在$map
中,不会编译出CSS,其实在Sass中,map-get($social-colors,weibo)
返回了一个null
值。但在编译出来的CSS中,你只知道他没有编译出样式,而且在命令终端编译时,也没有任何错误或者警告信息。说实话,你并不知道他为什么编译不出来样式,或者说他已返回了值为null
。体验不强,也不好排错。其实哪果我们自定义一个函数,另外加个判断,那就截然不同。
map-has-key($map,$key)
函数将返回一个布尔值。当$map
中有这个$key
,则函数返回true
,否则返回false
。
前面的示例,当$key
不在$map
中时,使用map-get($map,$key)
函数将返回一个null
值。但对于开发人员,并看不到任何提示信息。如果使用map-has-key($map,$key)
函数就可以改变这一状态。我们来看一个简单的示例。
@if map-has-key($social-colors,facebook){
.btn-facebook {
color: map-get($social-colors,facebook);
}
} @else {
@warn "No color found for faceboo in $social-colors map. Property ommitted."
}
编译出来:
.btn-fackbook{
color: #3b5998;
}
上面看到的示例是facebook
这个key
已存在$social-colors
这个map
当中。所以能正常编译。如果你手误,将facebook
输错了:
@if map-has-key($social-colors,faceboo){
.btn-facebook {
color: map-get($social-colors,facebook);
}
} @else {
@warn "No color found for faceboo in $social-colors map. Property ommitted."
}
这个时候,你编译出来的CSS代码中,不会有新代码添加,但在命令终端可以看到提示信息:
WARNING: No color found for faceboo in $social-colors map. Property ommitted.
on line 25 of test.scss
是不是非常的友好。但总觉得这样写是傻傻的,总不可能每获取一个key
都写一个@if
语句吧。其实不用这么复杂,我们可以自定义一个函数,比如colors()
:
@function colors($color){
@if not map-has-key($social-colors,$color){
@warn "No color found for `#{$color}` in $social-colors map. Property omitted.";
}
@return map-get($social-colors,$color);
}
有了这个函数之后,我们就可以这样使用:
.btn-dribble {
color: colors(dribble);
}
.btn-facebook {
color: colors(facebook);
}
.btn-github {
color: colors(github);
}
.btn-google {
color: colors(google);
}
.btn-twitter {
color: colors(twitter);
}
.btn-weibo {
color: colors(weibo);
}
编译出来的CSS:
.btn-dribble {
color: #ea4c89;
}
.btn-facebook {
color: #3b5998;
}
.btn-github {
color: #171515;
}
.btn-google {
color: #db4437;
}
.btn-twitter {
color: #55acee;
}
同时你不难发现,命令终端提示信息:
WARNING: No color found for `weibo` in $social-colors map. Property omitted.
on line 13 of test.scss
那是在$social-colors
这个map
中没有weibo
这个key
。是不是很有意思。
当然,如果你对Sass的指令熟悉的话,上面编译出来的CSS可以使用@each
:
@each $social-network,$social-color in $social-colors {
.btn-#{$social-network} {
color: colors($social-network);
}
}
map-keys($map)
函数将会返回$map
中的所有key
。这些值赋予给一个变量,那他就是一个列表。如:
map-keys($social-colors);
其返回的值为:
"dribble","facebook","github","google","twitter"
换句话说:
$list: map-keys($social-colors);
相当于:
$list:"dribble","facebook","github","google","twitter";
这个时候,就可以配合Sass的list做很多事情。
上面的示例,可以做通过map-keys($map)
来做一个修改:
@function colors($color){
$names: map-keys($social-colors);
@if not index($names,$color){
@warn "Waring: `#{$color} is not a valid color name.`";
}
@return map-get($social-colors,$color);
}
上面代码中最不同之处,我们使用map-keys
将$social-colors
这个map
的所有key
取出,并赋予给一个名为$names
的列表。然后通过index($names,$color)
返回$color
在$names
位置,如果这个位置不存在,将返回提示信息,如果存在将返回正确的值。
.btn-weibo{
color: colors(weibo);
}
例如,weibo
不在$social-colors
中,那么不会编译出CSS,而且在命令终端同样会有提示信息:
WARNING: Waring: `weibo is not a valid color name.`
on line 27 of test.scss
同样,也可以通过@each
或者@for
遍历出所有值:
@each
@each $name in map-keys($social-colors){
.btn-#{$name}{
color: colors($name);
}
}
@for
@for $i from 1 through length(map-keys($social-colors)){
.btn-#{nth(map-keys($social-colors),$i)} {
color: colors(nth(map-keys($social-colors),$i));
}
}
虽然使用的方法不一样,但最终得到的CSS是一样的:
.btn-dribble {
color: #ea4c89;
}
.btn-facebook {
color: #3b5998;
}
.btn-github {
color: #171515;
}
.btn-google {
color: #db4437;
}
.btn-twitter {
color: #55acee;
}
map-values($map)
函数类似于map-keys($map)
功能,不同的是map-values($map)
获取的是$map
的所有value
值,可以说也将是一个列表。而且,map-values($map)
中如果有相同的value
也将会全部获取出来。
如前面的示例,使用:
map-values($social-colors)
将会返回:
#ea4c89,#3b5998,#171515,#db4437,#55acee
值与值之前同样用逗号分隔。
map-merge($map1,$map2)
函数是将$map1
和$map2
合并,然后得到一个新的$map
。如果你要快速将新的值插入到$map
中的话,这种方法是最佳方法。假设我们有两个$map
:
$color: (
text: #f36,
link: #f63,
border: #ddd,
backround: #fff
);
$typo:(
font-size: 12px,
line-height: 1.6
);
如果希望将这两个$map
合并成一个map
,我们只要这样做:
$newmap: map-merge($color,$typo);
将会生成一个新的map
:
$newmap:(
text: #f36,
link: #f63,
border: #ddd,
background: #fff,
font-size: 12px,
line-height: 1.6
);
这样你就可以借助map-get()
等函数做其他事情了。
不过有一点需要注意,如果$map1
和$map2
中有相同的$key
名,那么将$map2
中的$key
会取代$map1
中的:
$color: (
text: #f36,
link: #f63,
border: #ddd,
backround: #fff
);
$typo:(
font-size: 12px,
line-height: 1.6,
border: #ccc,
background: #000
);
执行:
$newmap: map-merge($color,$typo);
得到的新map
:
$newmap:(
text: #f36,
link: #f63,
font-size: 12px,
line-height: 1.6,
border: #ccc,
background: #000
);
map-remove($map,$key)
函数是用来删除当前$map
中的某一个$key
,从而得到一个新的map
。其返回的值还是一个map
。map-remove($map,$key)
并不能直接从一个map
中删除另一个map
,仅能通过删除map
中的某个key
得到新map
。如:
$map:map-remove($social-colors,dribble);
返回的是一个新map
:
$map:(
facebook: #3b5998,
github: #171515,
google: #db4437,
twitter: #55acee
);
如果删除的key
并不存在于$map
中,那么map-remove()
函数返回的新map
和以前的map
一样。
$map:map-remove($social-colors,weibo);
返回的值:
$map: (
dribble: #ea4c89,
facebook: #3b5998,
github: #171515,
google: #db4437,
twitter: #55acee
);
keywords($args)
函数可以说是一个动态创建map
的函数。可以通过混合宏或函数的参数变创建map
。参数也是成对出现,其中$args
变成key
(会自动去掉$
符号),而$args
对应的值就是value
。
@mixin map($args...){
@debug keywords($args);
}
@include map(
$dribble: #ea4c89,
$facebook: #3b5998,
$github: #171515,
$google: #db4437,
$twitter: #55acee
);
在命令终端可以看到一个输入的@debug
信息:
DEBUG: (dribble: #ea4c89, facebook: #3b5998, github: #171515, google: #db4437, twitter: #55acee)
Sass的map
是一个强大的功能。他能帮助大家做很多有兴趣的事情。但map
也是个复杂的功能,如果没有理解清楚他的函数功能,发挥的作用会大大打折扣。当然,如果你对Sass熟悉的话,你可以在此基础上自定义一些与map
相关的函数,发挥其更大的优势。如果你对Sass的map
有相关的使用经验,希望与我们一起分享。