您的位置:首页 > 编程语言

使用Sass减少重复性代码

2015-09-06 09:03 344 查看
Hugo大师在understand Sass lists和ADVANCED
SASS LIST FUNCTIONS两篇文章中详细分析了Sass中list的功能,但在Sass中还有一个特性非常的有意思——变量插值。不管是列表,还是变量甚至说
@if
,
@for
,
@each
都是Sass中基础部分,仅从一个方面来看,并不能展示出Sass的魅力。反过来说,如果能将这几个部分结合在一起,那么将会给你的开发带来强大的方便性。今天我们就以Sass的变量作为话题的开端,来讨论Sass中变量配合其他功能另一用法。

在CSS的开发中,我们都在讨论OOCSS的使用,但其最终还是无法逃脱创建一些不使用的CSS代码。我们希望的是使用这些类产生的样式,需要的时候就产生CSS代码,不需要的时候就不产生CSS代码。希望做到的是真正按需生产,不产生额外的CSS代码。

来看一个典型的案例——Font Awesome图标制作,为了使用这个图标库里面的图标,在CSS的常规制作中,我们必须得将其样式导入进来。可是,很多时候,我们只需要其中的几个图标,换句话说,我只想给要的图标在样式中产生代码。在CSS中,我们无法实现,为了使用这个库,我们必须添加所有的图标类以及对应的相关代码。如此一来造成很多不需要的代码。

.icon-glass:before {
content: "\f000";
}
.icon-music:before {
content: "\f001";
}
.icon-search:before {
content: "\f002";
}
.icon-envelope-o:before {
content: "\f003";
}
.icon-heart:before {
content: "\f004";
}
.icon-star:before {
content: "\f005";
}
...

那么今天,我们就要来解决这个问题。

所需要的参数

欲解决上面提到的问题,我们在具体介绍详细的解决方案之前,我们需要一些参数。在Sass中,只要未调用,他是不会产生额外代码。此处我们主要借助Sass中的变量和列表来发力。

变量

大家都知道Font Awesome图标是通过字体来实现的,而其中每个图标都有其自身的实体编码,如
"\f000"
"\f001"
等等。当中就会有很多重复的代码,需要修复这些重复代码,我们就需要通过变量列表。首要条件是我们需要声明一些变量,我们把这些变量放在
_variables.scss
文件中。

$icon-glass: "\f000";
$icon-music: "\f001";
$icon-search: "\f002";
$icon-envelope-o: "\f003";
$icon-heart: "\f004";
$icon-star: "\f005";

列表

接下来,我们需要一个列表,方便后面的遍历。注意,变量插值不能直接通过Sass的内部指令来控制。我想要一个带有选择器和名称和变量的列表,可在Sass中(至少目前为止)还不支持这样的特性。为了实现这样这一点,我们不得不对代码做一个变通。

$icon_names: icon-glass icon-music icon-search icon-envelope-o icon-heart icon-star;
$icon_vars: $icon-glass $icon-music $icon-search $icon-envelope-o $icon-heart $icon-star;

解决方法

接下来,我们来看Sass中是如何解决这个问题,让你的代码在需要的时候产生。也就是说调用的时候就产生,不调用的时候不产生额外的CSS代码。本文主要通过以下几种方法来实现:

@each
方法

第一种文案是采用Sass的列表遍历功能,使用变量
$icon_names
做类名遍历:

@each $name in $icon_names {
//在这进行操作
}

这里使用了Sass的
@each
循环,在此处定义了一个新的变量
$name
。让变量
$name
$icon_names
进行遍历。在我们的示例中,
$name
会遍历
$icon_nam
列表中的每个值。在此处一共会做五次遍历。

在循环中我们要添加一些动作,让
$name
变成我们需要的东西。简单点说,
$name
遍历的是
$icon_names
列表,每遍历一次就得到我们需要的一个类名,比如说
.icon-glass
。在接下的来的例子中,我们使用
.#{$name}
来得到类名。并且在其中添加样式:

@each $name in $icon_names {
.#{$name} {
content: $icon_vars;
}
}

上面的循环中,我们通过
$name
变量的
@each
功能,使用
$icon_vars
得到需要的实体符。将上面的代码进行编译:

.icon-glass {
content: "\f000" "\f001" "\f002" "\f003" "\f004" "\f005"; }

.icon-music {
content: "\f000" "\f001" "\f002" "\f003" "\f004" "\f005"; }

.icon-search {
content: "\f000" "\f001" "\f002" "\f003" "\f004" "\f005"; }

.icon-envelope-o {
content: "\f000" "\f001" "\f002" "\f003" "\f004" "\f005"; }

.icon-heart {
content: "\f000" "\f001" "\f002" "\f003" "\f004" "\f005"; }

.icon-star {
content: "\f000" "\f001" "\f002" "\f003" "\f004" "\f005"; }

很接近我们需要的,但我们每一个类只需要对应的一个实体符,因此我们还需要做一定的处理。在这里我们创建一个新的变量
$i
。Sass将通过
index()
函数,遍历
$color_names
中的
$name
,得到对应的索引值,并赋予给变量
$i
:

$i: index($icon_names, $name);

现在我们已经得到了索引号,我们可以使用这个值遍历这两个列表。使用Sass的
nth()
函数,我们可以指定一个列表,然后使用
$i
值,指定列表中的一个特定的值给CSS的
content
属性。

@each $name in $icon_names {
$i: index($icon_names, $name);.#{$name} {
content: nth($icon_vars, $i);
}
}

上面的意思就是,指定列表
$icon_vars
中第
$i
个值给
contentn
属性。我们来看一个编译出来的CSS:

.icon-glass {
content: "\f000"; }

.icon-music {
content: "\f001"; }

.icon-search {
content: "\f002"; }

.icon-envelope-o {
content: "\f003"; }

.icon-heart {
content: "\f004"; }

.icon-star {
content: "\f005"; }

这就是我们需要的,但不是最理想的。

接下来,我们通过Sass的
%placeholder
@extend
来创建一些占伴符。通过对
%placeholder
的介绍
得知,
%placeholder
只是一个占位符,默认情况下是不产生任何CSS代码,这不正是我们想要的效果吗?

@each $name in $icon_names {
$i: index($icon_names, $name);%#{$name} {
content: nth($icon_vars, $i);
}
}

上面的代码编译后是得不到任何的CSS代码,要想上面的代码产生对应的CSS代码,我们需要在上面的代码基础上使用
@extend
扩展对应的
%placeholder
。在这个例子中,我们将看到再次遍历
$icon_vars
的值:

@each $name in $icon_names {
$i: index($icon_names, $name);.#{$name} {
@extend %#{nth($icon_names, $i)};
}
}

最终的代码:

$icon-glass: "\f000";
$icon-music: "\f001";
$icon-search: "\f002";
$icon-envelope-o: "\f003";
$icon-heart: "\f004";
$icon-star: "\f005";
$icon_names: icon-glass icon-music icon-search icon-envelope-o icon-heart icon-star; $icon_vars: $icon-glass $icon-music $icon-search $icon-envelope-o $icon-heart $icon-star;
@each $name in $icon_names {
$i: index($icon_names, $name);%#{$name} {
content: nth($icon_vars, $i);
}
}

@each $name in $icon_names {
$i: index($icon_names, $name);.#{$name} {
@extend %#{nth($icon_names, $i)};
}
}

编译出来的CSS:

.icon-glass {
content: "\f000"; }

.icon-music {
content: "\f001"; }

.icon-search {
content: "\f002"; }

.icon-envelope-o {
content: "\f003"; }

.icon-heart {
content: "\f004"; }

.icon-star {
content: "\f005"; }

@for
方法

在这个示例中,我们除了使用
@each
方法之外,还可以使用
@for
循环方法来处理。在
@for
循环的方法中,使用
length()
替代
index()


@for $i from 1 through length($icon_names) {
%#{nth($icon_names, $i)} {
content: nth($icon_vars, $i);
}
}

@for $i from 1 through length($icon_names) {
.#{nth($icon_names, $i)} {
@extend %#{nth($icon_names, $i)};
}
}

@function
方法

$icon_vars
可以通过创建一个函数功能进行查询。在我们的示例中,在
$icon_vars
中查询出对应的
$icon_names
对应的内容。

@function get-icon($search) {
$index: index($icon_names, $search);
@return nth($icon_vars, $index);
}

在这个示例中,
$search
是我们在
$icon_names
查找的icon对应的类名。相对应函数返回的icon对应的实体符。我们可以使用一种简单的方法直接在函数中嵌套
index()
函数。

@function get-icon($search) {
@return nth($icon_vars, index($icon_names, $search));
}

使用
@function
方法,同样在默认情况下是不会有任何的样式产生的,只有通过下面的方式调用的时候才会产生代码:

.icon-glass {
content: get-icon("icon-glass");
}

编译出来的CSS:

.icon-glass {
content: "\f000"; }

这种方法才是我们真正想要的方式,真正叫按需产生。

除了上述的方法之外,我们还可以结合前面的知识做一个调整。

我可以单独的以
key=>value
的方式创建一个简单的Sass列表,例如:

$icons:
glass "\f000",
music "\f001",
search "\f002",
envelope-o "\f003",
heart "\f004",
star "\f005"
;

同样,我们可以通过nth()函数功能,从
$icons
中检索中数字检索出对应的值:

.icon-glass {
content: nth($icons,1);
}

编译出来的CSS:

.icon-glass {
content: glass "\f000"; }

这样的结果并不是我们需要的。为了解决这个问题,我们需要创建一个Sass函数,返回一个键名
key
和其对应的值
value
。也就是前面所说的
key=>value
所对应的效果:

@function get-icon($icon-name){
//$icons列表做循环
@each $icon in $icons {
//如果关键词key(第一个元素是当前的$icon)一样,参数指定返回的值
@if nth($icon, 1) == $icon-name {
@return nth($icon,2);
}
}
}

现在,我们可以使用
get-icon
函数返回需要的值,达到按需产出:

.icon-glass {
content: get-icon(glass);
}

编译出来的CSS:

.icon-glass {
content: "\f000"; }

最后列出,这种方法所使用的所有Sass代码:

$icons:
glass "\f000",
music "\f001",
search "\f002",
envelope-o "\f003",
heart "\f004",
star "\f005"
;
@function get-icon($icon-name){
@each $icon in $icons {
@if nth($icon, 1) == $icon-name {
@return nth($icon,2);
}
}
}

.icon-glass {
content: get-icon(glass);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: