Sass 编写组件

发布于 12-10 12:51 字数 5738 浏览 1188 评论 0

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

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

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

定义警告信息颜色

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

  • 验证(Validation)
  • 错误(Error)
  • 警告(Warning)
  • 信息(Information)

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

  • 成功定义绿色(Green)
  • 错误定义红色(Red)
  • 警告定义黄色(Yellow)或橙色(Orange)
  • 信息定义淡蓝

基本样式

所有警告信息类型都具有相同的样式,比如说内距 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 传递更多的参数。

@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中新增加了一个功能: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 展示了一个演示示例:http://codepen.io/anon/embed/Dzloe

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

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

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

发布评论

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