理解 Sass 中变量作用域
在这篇文章中我们将一起深入探讨Sass的变量和变量作用域。变量作用域的描述是根据上下来定义和在哪使用变量。
首先,我们将介绍 Sass 作用域范围。然后,将解释两个用在变量值中标签,这两个标签非常有用。最后将简单介绍可用的函数,用来检查是否存在一个变量。
Sass 变量作用域
Sass 支持两种类型变量:局部变量和全局变量。
默认情况之下,所有定义在任何选择器之外的变量被认为是全局变量。这意味着他们可以在样式表中任意地方被访问。例如,这里有一个全局变量:
$bg-color: green;
另一方面,定义在选择器内的变量称之为局部变量。后面我们将研究如何自定义他们的行为。但是现在,让我们看看我们的第一个示例。
在这里,我们定义了一个 混合宏,然后在里面设置了一个 $btn-bg-color
变量。这是一个局部变量,他只在 mixin 内部可见:
@mixin button-style {
$btn-bg-color: lightblue;
color: $btn-bg-color;
}
接下来,我们调用这个 mixin:
button {
@include button-style;
}
编译出来的 CSS:
button {
color: lightblue;
}
然而,想象一下,我们也使用这个变量(但不是 mixin),而是在一个选择器中:
.wrap {
background: $btn-bg-color;
}
此时,编译器(命令终端)会报这样的错误:
Undefined variable: "$btn-bg-color".
这是可以预料的是吧?我们试图在一个混合宏中调用一个局部变量。别担心,正如上面提到的,接下来的内容,我们会解决这个问题。
嵌套选择器
值得一提的是,如果我们在一个选择器内声明了一个变量,嵌套在里面的其他选择器中都可以访问它。这里有一个例子:
.wrap {
$bg-color: red;
&:after {
background: lighten($bg-color, 10%);
}
}
编译出来的 CSS:
.wrap:after {
background: #ff3333;
}
然而,看看下面的例子,我们定义了一个函数,然后在嵌套的选择器中使用这个函数:
@function my-function() {
$text-color: black;
@return $text-color;
}
.wrap {
color: my-function();
&:after{
background: $text-color;
}
}
如果我们试图编译这个,我们会得到同样的错误。
Undefined variable: "$text-color".
再一次,这是因为我们无法访问 $text-color
变量。它不是直接定义在你选择器,而是在选择器内部调用了定义的函数。
变量名称
全局变量和局部变量可以定义相同的变量名。我们通过下面的示例来证明这一点:
$text-color: tomato;
@mixin button-style {
$text-color: lime;
color: $text-color;
}
@mixin link-style {
$text-color: black;
color: $text-color;
}
我们定义了三个相同变量名的变量,只是他们具有不同的值。第一个是全局变量,其他两个是局部变量。
在样式这样调用他们:
button {
@include button-style;
}
a {
@include link-style;
}
.wrap {
background: $text-color;
}
编译出来的 CSS:
button {
color: lime;
}
a {
color: black;
}
.wrap {
background: tomato;
}
这是你所期望的结果?
请记住,除非我们使用 Sass 当前版本(3.4版本)编译,不然是看不到这些样式。比如说,假设我们使用的是 Sass 3.3 版本,那么编译出来的CSS像这样:
button {
color: lime;
}
a {
color: black;
}
.wrap {
background: black;
}
很明显,.wrap
选择器的背景颜色不同。早些Sass版本(LibSass也一样)说,如果我们在本地重新定义了一个全局变量(如text-color
),这将是新的全局变量。所以,在我们的示例中编译样式时取决于我们声明的变量的顺序和mixin的顺序。
default 标志
这个标志让我们设置一个变量值,以防还没有设置或这个变量的值为 null
(视为未赋值)。更好的解释是我们在真实的场景中使用他,假设我们有一个这样的项目,其结构如下:
Project-Name/
├── ...
├── css/
│ └── app.css
└── scss/
├── _config.scss
├── _variables.scss
├── _mixins.scss
└── app.scss
app.scss
文件有这样一段代码:
@import "config";
@import "variables";
@import "mixins";
button {
@include button-style;
}
// more styles
让我们来看看部分文件中的内容。
首先在 variables,scss
文件中包含了我们要用的变量:
$btn-bg-color: lightblue !default;
$btn-bg-color-hover: darken($btn-bg-color, 5%);
// more variables
注意在btn-bg-color
变量的值后面添加了一个default
标志。
其二,在mixins.scss
文件中包含了我们要使用的混合宏:
@mixin button-style ($bg-color: $btn-bg-color, $bg-color-hover: $btn-bg-color-hover) {
background-color: $bg-color;
// more styles
&:hover {
background-color: $bg-color-hover;
// more styles
}
}
// more mixins
然而,在编译出来的app.css
文件中的代码将像下面:
button {
color: lightblue;
}
button:hover {
background-color: #99cfe0;
}
所以,我们的按钮采用的是默认样式。但是,假设我们想要通过自定义一个值来覆盖他们。要做到这一点,我们可以在config.scss
文件中重新分配(默认)变量:
$btn-bg-color: chocolate;
// more variables
设置的变量值为chocolate
将导致变量会忽略带有default
标记的lightblue
值。因此,生成的CSS将会变成下面这样:
button {
color: chocolate;
}
button:hover {
background-color: #bc5e1b;
}
注:我们在btn-bg-color
变量后面没有添加default
标记。编译出来的CSS将像这样:
button {
color: lightblue;
}
// hover styles
global标志
第二个标志帮助我们改变一个局部变量的作用范围。
不知道你是否还记得我们第一个示例编译时出现的错误?那么好,因为我们试图在.wrap
选择器中使用btn-bg-color
变量。让我们来修改一下我们的示例,在变量的值中添加global
新标志。下面是修改后样式:
@mixin button-style {
$btn-bg-color: lightblue !global;
color: $btn-bg-color;
}
button {
@include button-style;
}
.wrap {
background: $btn-bg-color;
}
正如下面所示代码,因为有了这个标志,编译时不会有报错代码:
button {
color: lightblue;
}
.wrap {
background: lightblue;
}
global
标志是用的,但得记住,总是通过这个标志来修改一个变量的范围并不是一个很好的实践。
检查一个变量是否存在
Sass提供了两个函数,用来测试一个变量是否存在。我们可以使用variable-exists
或global-variable-exists
函数来检查我们的局部变量或全局变量是否分别存在。
举例来说,这是一个常见的示例。我们定义了一个变量,变量值是引用Google Fonts的一个绝对路径。然后,我们在样式表中选择字体,但前担是相关的变量被实例化。
$google-font: "http://fonts.googleapis.com/css?family=Alegreya";
@if(global-variable-exists(google-font)) {
@import url($google-font);
}
结果是:
@import url("http://fonts.googleapis.com/css?family=Alegreya");
结论
在这篇文章中,我们介绍了Sass变量作用域的概念。通过不同的示例,让我们更能清楚的了解变量作用域,所以希望你现在能更好的理解变量的作用域是如何工作的。你可以在SassMeister中找到本文用到的所有例子。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论