Sass 3.3 新特性之连体符 & - 文章教程

Sass 3.3 新特性之连体符 &

发布于 2021-08-16 字数 8974 浏览 904 评论 0

Hugo Giraudel 在《Looking Into the Future of Sass》一文中向大家介绍了Sass的十大新特性。这些特性都将让你的工作变得更简单与方便。那么今天我主要想向大家介绍我自己对Sass3.3中几个新特性的理解与使用心得,希望对大家的学习有所帮助。

在 Sass 中使用连体符 &

在 Sass3.3 中,连体符 & 让你的选择器变得更简单,维护更方便。他可以轻松的让你选择父元素,可以配合伪类元素等。但在 Sass 中还有一个新的用法,如:

$selector: null;
.block{
    $selector: &;
}
#{$selector}--map {
    color: green;
}

编译出来的CSS:

.block--map {
  color: green; 
}

但此时Sass编译器将报出错误信息:

DEPRECATION WARNING on line 6 of test.scss:
Assigning to global variable "$selector" by default is deprecated.
In future versions of Sass, this will create a new local variable.
If you want to assign to the global variable, use "$selector: & !global" instead.

根据报警提示,我们将上面的代码进行修改,在代码中加入!global:

.block{
    $selector: & !global;
}
#{$selector}--map {
    color: green;
}

编译出来的CSS:

.block--map {
  color: green; 
}

和第一种方法编译出来的CSS是一样的。此时试想,如果我们的代码中有不同的BEM命名方式,比如在CSS中有这样的一段代码:

.view-element {...}
.block-element {...}

根据前面的示例,大家可能第一时间想到是:

.view,
.block {
    $selector: & !global;
}
#{$selector}--element{
    color:green;
}

但这段SCSS代码编译出来的CSS并不是我们想要的代码:

.block, 
.view--element {
  color: green; 
}

或许你会考虑这样来重构SCSS代码:

.block{
    $selector: & !global;
}
.view {
    $selector: & !global;
}
#{$selector}--element {
    color: green;
}

但编译出来的CSS还不是你想要得到的:

.view--element {
  color: green; 
}

很明显 .view 覆盖了 .block 中的 $selector: & !global。但仍不死心,在nex3/sass上提了一个issues@lolmaus提供了一种方法

.block,
.view {
    $selectors: & !global;
}
@each $selector in $selectors {
    #{$selector}--element {
        color: green;
    }
}

编译出来CSS:

.block--element {
  color: green; 
}

.view--element {
  color: green; 
}

这似乎是我们想要的CSS代码,但换一个条件:

.block-element {color:green;}
.view-element {color: blue;}

那么目前为止,在Sass使用!global中还无法实现。只能变换一种方式:

$selector: null;
.block {
    $selector: &;
}
#{$selector}--element{
    color: green;
}
.view {
    $selector: &;
}
#{$selector}--element{
    color:blue;
}

这样编译出来的CSS是我们所需要的:

.block--element {
  color: green; 
}

.view--element {
  color: blue; 
}

虽然实现我们需要的效果,但似乎这样的SCSS代码并没有给我们的工作带来方便。当然,在Sass中还有一种更容易实现的方法,这也是Sass3.3中的另一个新特性,稍后需要描述的。不过在这里,通过多种方式演示,唯一想说明的一点是在Sass3.3中新引入了一个!global,它可以用来定义某个选择器为全局选择器变量或者定义全局变量。等同效果:

//方法一
$selector: '.selector';
#{$selector}--element {
    background-color: #fcc;
}
//方法二
.selector {
    $selector: & !global;
}
#{$selector}--element {
    background-color: #fcc;
}

CSS:

.selector--element {
  background-color: #fcc; 
}

但有一点需要特别声明,!global !default 并不相同。

!default VS !global

!default在Sass中常称为变量默认值,而!global在Sass中称为变量全局值。这好象又回到了全局变量和局部变量的争论中了。有关于这两个方面的争论,我们避而不谈,主要还是来看看他们功能上的区别。

首先我们简单的回忆一下这样的一个示例:

p {
    $color: green;
    color: $color;
    a {
        color: $color;
    } 
}

div {
    color: $color;
}

在编译Sass时将会报错:

error test.scss (Line 16: Undefined variable: "$color".)

错误信息告诉我们,在div中的$color是没有定义的一个变量值。为了能让代码正常运行,必须先得在外面显式的声明$color变量。

$color: blue;

p {
    $color: green;
    color: $color;
    a {
        color: $color;
    } 
}

div {
    color: $color;
}

编译出的CSS:

p {
  color: green; 
}
p a {
  color: green; 
}

div {
  color: green; 
}

那么在Sass3.3中,我们可以借助于!global在任何地方定义一个变量,而且任何一组代码中都可以调用这个变量:

p {
    $color: green !global;
    color: $color; //输出green
    a {
        color: $color; //输出green
    } 
}

div {
    color: $color; //输出green
}

使用!global之后,将不会报错,编译出来的CSS也无误。

另外在使用!global依旧无法避免顺序造成的覆盖,我们来尝试一个新示例:

p {
    $color: green !global;
    color: $color; //输出green
    a {
        $color: red;
        color: $color; //输出red
    } 
}

div {
    color: $color; //输出red
}

回到!default中,大家都知道同一变量后面出现的总是会覆盖前面出现的:

$color: blue;
$color: red ;

p {
    color: $color; //输出red
    a {
        color: $color; //输出red
    } 
}

div {
    color: $color; //输出red
}

一旦在第二个变量加上!default之后,那么一切将有可能改变:

$color: blue;
$color: red !default;

p {
    color: $color; //输出blue
    a {
        color: $color; //输出blue
    } 
}

div {
    color: $color; //输出blue
}

但要是将后面出现的$color变量后添加!global,那依旧是后者覆盖前者:

$color: blue;
$color: red !global;

p {
    color: $color; //输出red
    a {
        color: $color; //输出red
    } 
}

div {
    color: $color; //输出red
}

而这种方式也将无任何意义。

通过这些对比,我们可以得出:!default 可以用来设置一个默认变量,其不会覆盖前面设置的相同变量;而!global可以在任何代码块中声明一变量,提供给其他代码块调用此变量。

& 另一用法 #{&}

在Sass中&配上#{}可以做为选择器插值。当然,这个在生成后代选择器的时候非常方便,简单的看个示例:

block {
    #{&} .bar {
        color: red;
    }
}

编译出CSS:

.block .block .bar {
  color: red; 
}

似乎把我们的CSS变得更为复杂,但其还是具有一定的优势的,比如在BEM的应用中:

.block {
    #{&}--element {
        color: red;
    }
}

编译出CSS:

.block .block--element {
  color: red; 
}

编译出来的样式代码,虽然离BEM的初衷甚远,但也免强可一用。不过在Sass3.3中有一个新的特性@at-root可以更好的配合BEM一起使用。

@at-root

在Sass中,如果你不想嵌套选择器,可以使用@at-root特性。当像使用#{&}可以明确的告诉Sass,他只是一个变量,而不会嵌套。来看一个示例:

.block {
    @at-root #{&}__element {
        color: red;
    }
    @at-root #{&}--modifier{
        color:green;
    }
}

编译出CSS:

.block__element {
  color: red; 
}
.block--modifier {
  color: green; 
}

生成的CSS代码正是我们想要的BEM模式。也就是说,有了@at-root可以非常简单的实现BEM模式。在Sass中除了这种方式之外,还可以将@at-root以块的方式展示:

.block {
    @at-root {
        #{&}__element {
            color: red;
        }
        #{&}--modifier{
            color:green;
        }
    }
}

同样可以编译出来上一段相同的CSS代码。

总结

他可以让你的选择器嵌套更便捷,而且可以配合#{}实现选择器的插值。另外通过与!global的配合可以指引定选择器为变量。另外最大的优势是,配合@at-root可以与BEM完美的结合,真正实现BEM的设计模式。

希望这些简单的示例,能帮助大家更好的理解&和更好的使用&符。

更多内容参见:https://www.wenjiangs.com/article/sass-and-conjoined-character.html

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

目前还没有任何评论,快来抢沙发吧!

关于作者

清晨说ぺ晚安

我之所以活到现在的全部意义,是为了此刻能对你说,我爱你,我会在你身后永远守护你。

16 文章
2 评论
21567 人气
更多

推荐作者

qianbiandeboy

文章 0 评论 0

少女净妖师

文章 2 评论 0

zangqw

文章 0 评论 0

qq_7HKsl

文章 0 评论 0

伪装你

文章 1 评论 0