Sass Maps 介绍和使用

发布于 2021-10-29 12:32:03 字数 14075 浏览 1413 评论 0

对于一位程序员来说,对数组并不会陌生。但对于前端人员(像我这样不算前端的前端)对于数组,只是听过,看过,但不知道如何使用?然而在 Sass3.3 版本中开始引入一个新的数据类型maps,他长得跟数组非常的相似。但也让我极其的苦逼,因为我不懂数组呀,不知道如何下手开始使用 Sass 的 map 功能。

通过阅读一些文章,觉得 Sass 的 map 是 Sass 的强大的特性之一,能帮助我们做好更多的事情,比如说 管理媒体查询的断点、管理 z-index 的值、管理颜色管理排版 等。接下来,我们一起来学习 Sass 的 map

Sass Maps 语法

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 的形式赋予,其中keyvalue是成对出现,并且每对之间使用逗号(,)分隔,其中最后一组后面没有逗号。

其中键 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,但建议不这样使用。

Sass Maps 的函数

前面介绍了使用map来管理变量,但要在Sass中获取变量,或者对map做更多有意义的操作,我们必须借助于map函数功能。在Sass中map自身带了七个函数:

接下来,我们先简单的了解这些函数的具体使用以及所具有的功能。

map-get($map,$key)

map-get($map,$key)函数的作用是根据$key参数,返回$key$map中对应的value值。如果$key不存在$map中,将返回null值。此函数包括两个参数:

  • $map:定义好的map
  • $key:需要遍历的key

来看一个简单的示例,假设定义了一个$social-colorsmap:

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

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-remove($map,$key)函数是用来删除当前$map中的某一个$key,从而得到一个新的map。其返回的值还是一个mapmap-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)

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 相关的函数,发挥其更大的优势。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。