Sass编写组件

本文由大漠根据Hugo Giraudel的《A Sass Component in 10 Minutes》所译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处,还请同行朋友指点。如需转载此译文,需注明英文出处:http://www.sitepoint.com/sass-component-10-minutes/,以及作者相关信息。

——作者:Hugo Giraudel

——译者:大漠

很多开发者都认识到,在网站或应用程序的开发中使一些组件非常强大,但是这些组件开发起来并不是一件易事。今天我们就一起来探讨一下如何使用Sass来开发组件。

因为讲述任何东西都没有直接拿用例来介绍更好,我建议我们要采用的示例是大家在网站或应用程序开发中几乎都有用过的,一个响应用户交互的——警告信息(也有很多人称之为“通知”)。

使用Sass来创建一个处理不同类型的警告信息的组件是一个很完美的示例,同时还能提高你使用Sass的技术。所以,伙计们,还在犹豫什么,赶紧动手一试吧。

定义警告信息颜色

我们想做什么?消息!但是,是一个什么样的消息呢?让我们参考BootStrap框架做好的消息框吧:BootStrap为警告信息定义了四种类型

这个组件示例对于我们听起来不错哟。类似于我们现实生活中一样,用不同的语气来表达不同的感情,我们可以用不同的颜色定义信息,在网络上传达不同类型的警报信息。因此,四种不同类型的警报信息用不同的颜色方案来表示他们的状态。再次,我们还是借助Bootstrap来完成我们的警报信息不同类型的颜色定制:

基本样式

所有警告信息类型都具有相同的样式,比如说内距padding、外距margin和一些排版本的样式。最后,他们不同的地方是采用不同的颜色来区分不同类型的警告信息。

正如在我写的文章《Sass: Mixin or Placeholder?》中讨论的一样。最好的做法是使用%placeholder创建一个静态规则和使用@mixin创建一个动态规则(也就是那些会根据上下文变量发生变化)。

那我们就先从%placeholder入手吧:

%message {
  padding: .5em;
  margin-bottom: .5em;
  border-radius: .15em;
  border: 1px solid;
}

首先要注意的是,我们没有指定任何有关于字体方面的样式,比如字号、字体或行高。因为这个组件还会在别的地方使用,这有助于组件更独立。

我们也没有为边框设置颜色。border-color使用的都是默认值currentcolor,很多客户端,color的默认值为黑色black

接下来我们来写@mixin

@mixin message($color) {
  @extend %message;
  color: $color;
  border-color: lighten($color, 20%);
  background: lighten($color, 40%);
}

正如你所看到的,@mixin message做了两件事情:首先设置了颜色相关的属性,并且接受一个独物的颜色做为参数;其次使用了Sass中的lighten()颜色函数创建了两个新颜色。使用Sass的颜色函数是一个很好的功能,他还可以减少在@mixin传递更多的参数。

如果您从未接触过Sass的颜色函数功能相关的知识,你要是感兴趣的话可以点击早前写过的《Sass基础——颜色函数》一文。——@大漠

@mixin message做的第二件事情,就是通过@extend扩展了前面定义的placeholder——%message。这样你就没有必要为每种不同类型的警告信息重写这些样式。而且代码变得干净(因为代码不需要重复的写)。

调用@mixin

我们几乎完成了整个组件的制作,接下来要做的事情就是为每种不同类型的警告信息调用@mixin message,并且传递正确的颜色值。我们希望的信息类型是:

.message-error {
  @include message(#b94a48);
}

.message-valid {
  @include message(#468847);
}

.message-warning {
  @include message(#c09853);
}

.message-info {
  @include message(#3a87ad);
}

让事情变得更有意思

我们迄今所做的已经非常简洁了。添加一个新的警报类型只需要到刚创建的类名中@include定义好的@mixin message和传递你所选择的颜色而以。但是,如果我们想让它更便于携带呢?

那是不是有一种更好的方法,给不同的类型的警告信息映射对应的颜色呢?回答是肯定的:嵌套列表。创建一个二维列表,并通过Sass的循环特性,我们就可以很容易的做到这一点。

$message-types: (
  (error    #b94a48)
  (valid    #468847)
  (warning  #c09853)
  (info     #3a87ad)
) !default;

@each $message-type in $message-types {
  $type:  nth($message-type, 1);
  $color: nth($message-type, 2);

  .message-#{$type} {
    @include message($color);
  }
}

这段Sass代码和前面代码都产生相同的效果。除了设置了在变量中设置了一个列表,还可以将这个列变移到你的样式文件或者配置文件的顶部,使它更容易添加、编辑和删除一个警告类型。

注意:如果你想把这个加到一个库或框架中,在$message-types变量后面添加!default标记,这样一来,你就可以很好的在库或框架中覆盖这个变量。

使用Sass Map (Sass3.3)

在Sass3.3中新增加了一个功能:Maps。Maps就像PHP中的关联数组或像JavaScript中的对象。不管像什么,其主要功能是从一个值映射到另一个值中。

$message-types: (
  error   :  #b94a48,
  valid   :  #468847,
  warning :  #c09853,
  info    :  #3a87ad
) !default;

@each $type, $color in $message-types {
  .message-#{$type} {
    @include message($color);
  }
}

是不是很棒呀!

优雅处理错误信息

Sass开发者通常容易忽略的一件事情就是妥善处理错误的能力。你应该为你自定义的函数或mixin始终传递一个正确的参数,如果不是,就提供一个警告信息。这是不是让Sass在编译失败的时候做得更好呢?

在我们的这一个示例中,我们要确认给mixin传给$color参数的值的确是一个颜色。

@mixin message($color) {
  @if type-of($color) == color {
    @extend %message;
    color: $color;
    border-color: lighten($color, 20%);
    background: lighten($color, 40%);
  }

  @else {
    @warn "#{$color} is not a color for `message`.";
  }
}

这可以有效的防止Sass在编译无效的颜色时崩溃。此外,他告诉开发者,他给Mixin传入了一个错误的参数。这有可能错了一个字母或者更深一层的东西,不管是什么,总之它能帮助你。

总结

大约三十行的SCSS代码,我们已经成功的编写了一个组件,而且这个组件:

这是一套很好的规则,它适合于所有组件的开发。下面在Codepen展示了一个演示示例:

【更新】Sass: map-get

这篇更新是由wo_is神仙提供的源码。在这个更新中使用了Sass的新特性Map。感兴趣的同学可以仔细看看源码:

$message-colors: (
  success: (
    text: #468847,
    background: #dff0d8,
    border: darken(adjust-hue(#dff0d8, -10), 5%)
  ),
  error: (
    text: #b94a48,
    background: #f2dede,
    border: darken(adjust-hue(#f2dede, -10), 3%)
  ),
  warning: (
    text: #c09853,
    background: #fcf8e3,
    border: darken(adjust-hue(#fcf8e3, -10), 3%)
  ),
  info: (
    text: #3a87ad,
    background: #d9edf7,
    border: darken(adjust-hue(#d9edf7, -10), 7%)
  )
) !default;
//Define placeholder for default style

%message {
	padding: 0.5em;
	margin-bottom: 0.5em;
	@include border-radius(0.15em);
	border: 1px solid;
}

@each $type, $colors in $message-colors {
  .message-#{$type} {
    @extend %message;
    border-color: map-get($colors, border);
    background-color: map-get($colors, background);
    color: map-get($colors, text);

    a {
      color: darken(map-get($colors, text), 10%);
    }
  }
}

译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!

出处:

英文原文:http://www.sitepoint.com/sass-component-10-minutes/

中文译文:http://www.w3cplus.com/preprocessor/sass-component-10-minutes.html