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