Sass 两个先进特性与局限性

我真的很喜欢 Sass,并且在我的日常工作中很多时候在使用 Sass。他有很有很有用的功能。但是有很些东西我想做却不能做,他的语法和功能有所限制。今天我想分享一下我在使用Sass的一些发现,同时我也想知道你是否碰到这些限制以及你又是如何绕过他们。

插值 Interpolation

使用CSS预处理器语言的一个主要原因是想使用 Sass 获得一个更好的结构体系。比如说你想写更干净的、高效的和面向对象的CSS。Sass 中的插值(Interpolation)就是重要的一部分。让我们看一下下面的例子:

$properties: (margin, padding);

@mixin set-value($side, $value) {

@each $prop in $properties {

#{$prop}-#{$side}: $value;

}

}

.login-box {

@include set-value(top, 14px);

}

它可以让变量和属性工作的很完美,上面的代码编译成CSS:

.login-box {

margin-top: 14px;

padding-top: 14px;

}

这是Sass插值中一个简单的实例。当你想设置属性值的时候你可以使用字符串插入进来。另一个有用的用法是构建一个选择器。可以这样使用:

@mixin generate-sizes($class, $small, $medium, $big) {

.#{$class}-small { font-size: $small; }

.#{$class}-medium { font-size: $medium; }

.#{$class}-big { font-size: $big; }

}

@include generate-sizes("header-text", 12px, 20px, 40px);

编译出来的CSS:

.header-text-small { font-size: 12px; }

.header-text-medium { font-size: 20px; }

.header-text-big { font-size: 40px; }

一旦你发现这一点,你就会想到超级酷的 mixins,用来生成代码或者生成另一个 mixins。然而,这并不完全是可能的。第一个限制,这可能会很删除用于Sass变量的插值。

$margin-big: 40px;

$margin-medium: 20px;

$margin-small: 12px;

@mixin set-value($size) {

margin-top: $margin-#{$size};

}

.login-box {

@include set-value(big);

}

上面的Sass代码编译出来,你会得到下面的信息:

error style.scss (Line 5: Undefined variable: "$margin-".)

所以,#{} 语法并不是随处可用,你也不能在 mixin 中调用:

@mixin updated-status {

margin-top: 20px;

background: #F00;

}

$flag: "status";

.navigation {

@include updated-#{$flag};

}

上面的代码在编译成CSS时同样会报错:

error style.scss (Line 7: Invalid CSS after "...nclude updated-": expected "}", was "#{$flag};")

幸运的是,可以使用 @extend 中使用插值。例如:

%updated-status {

margin-top: 20px;

background: #F00;

}

.selected-status {

font-weight: bold;

}

$flag: "status";

.navigation {

@extend %updated-#{$flag};

@extend .selected-#{$flag};

}

上面的Sass代码是可以运行的,因为他给了我们力量,可以动态的插入.class%placeholder。当然他们不能接受像mixin这样的参数,上面的代码编译出来的CSS:

.navigation {

margin-top: 20px;

background: #F00;

}

.selected-status, .navigation {

font-weight: bold;

}

在Sass的社区正在积极讨论插值的局限性,谁又知道呢,也许我们很快将能够使用这些技术也说不定呢。

使用列表作为一个源生成器

如果你在函数或mixin中需要未知数量的参数,这个列表就显得非常的有用。前几天,我遇到了一个问题,我没能解决,至使我不得不改变我的Sass架构。假设我们有下面一段代码:

%margin-reset { margin: 0; }

%padding-reset { padding: 0; }

%size-reset { width: 100%; height: 100%; }

@mixin add-styles($items) {

@each $item in $items {

@extend %#{$item};

}

}

.footer, .header, .login-box {

@include add-styles((

margin-reset,

padding-reset,

size-reset

));

}

编译出来的CSS:

.footer, .header, .login-box {

margin: 0;

}

.footer, .header, .login-box {

padding: 0;

}

.footer, .header, .login-box {

width: 100%;

height: 100%;

}

到目前为止还好。现在我能够使用@extend扩展我想要的很多%placeholders。但mixins呢?我在想可以用mixin代替%placeholders嵌套吗?第一个问题是,mixins接受参数(如果你有一个不行,就必须考虑重构)。正如你已经看到,主要的想法是通过一个列表,通过后面的元素来读取。每个元素可以是一个mixin或者%placeholders。我发现只有一种方式来区分它们。如果我需要扩展一个占位符,我需要传它的名字,否则我通过另一个列表包含mixin的名称及其参数。例如:

@mixin border-solid($width, $color) {

border: solid #{$width} #{$color};

}

...

.footer, .header, .login-box {

@include add-styles((

margin-reset,

padding-reset,

size-reset,

(border-solid, 3px, #F90)

));

}

所以,当我遍历列表中的所有列表项时我必须先检查当前的一个列表。幸运的是有一个函数称为type_of和它返回传递的变量的类型。

@mixin add-styles($items) {

@each $item in $items {

@if type_of($item) == "list" {

// call a mixin

} @else {

@extend %#{$item};

}

}

}

就像我说的,在本文的第一部分,我们在mixin中不能用插值。像这样的代码实际上是错误的:

@include #{$item}();

据我所了解,目前没有解决方案,和我使用的一个@if...@else

@mixin add-styles($items) {

@each $item in $items {

@if type_of($item) == "list" {

@if nth($item, 1) == "border-solid" {

@include border-solid(nth($item, 2), nth($item, 3));

}

} @else {

@extend %#{$item};

}

}

}

当然我也不喜欢这样的代码。主要是因为我想用它来描述每一个mixin在添加样式。不管怎么样,我是准备使用它,即使这个版本没有工作。一旦我删除%placeholders和只调用(border-solid,3px,#f90),会得到:

Syntax error: Invalid CSS after "%": expected placeholder name, was "3px"

如果你有一个元素的列表它被转换为字符串和我用来检查 @if type_of($item) == "list" 不能正常工作,将会得到一个@else参数和试图@extend一个%placeholder

总结

虽然 Sass 有一定的局限性,但 Sass 仍然是一个美妙的预处理器语言,他带来很多有用的特性。

以上是 Sass 两个先进特性与局限性 的全部内容, 来源链接: utcz.com/z/264226.html

回到顶部