scss的@import 和 @use的区别,常见的函数使用,@mixin @include @extends @each 等使用

1,538 阅读7分钟

传送门:Sass中文网 传送门:Sass 教程 | 菜鸟教程

关于@use和@import的区别

功能/特性@import@use
作用域共享同一个作用域创建命名空间,具有隔离性
重复加载可能导致重复加载保证每个模块只加载一次
推荐版本较旧版本的导入方式新版本 Sass 推荐的导入方式
命名空间可以自定义命名空间
模块化支持较弱提供更好的模块化支持
性能可能存在性能问题更优化的性能
避免全局污染不提供隔离性提供隔离性
导入方式使用 @import 导入使用 @use 导入

上面表格就列出了二者的区别,然后我们来重点看一下重复加载命名空间

重复加载

当使用 @import 导入模块时,如果在多个文件中多次导入同一个文件,可能会导致重复加载的问题。这意味着被导入的文件将在每个使用了 @import 的文件中都被加载一次,导致样式表中包含多份相同的样式,从而影响性能和增加文件大小。

让我们通过一个示例来说明重复加载的问题:

假设有以下两个 SCSS 文件:

文件:_variables.scss

// _variables.scss $primary-color: #007bff; $secondary-color: #6c757d;

文件:styles1.scss

// styles1.scss @import 'variables'; body { background-color: $primary-color; }

文件:styles2.scss

// styles2.scss @import 'variables'; button { background-color: $secondary-color; }

在这个示例中,我们有两个样式文件 styles1.scssstyles2.scss,它们分别使用 @import 导入了同一个 _variables.scss 文件。由于 styles1.scssstyles2.scss 都导入了 _variables.scss,在编译这两个样式文件时,_variables.scss 将被加载两次。

编译后的结果如下所示:

编译后的 styles1.css

/* _variables.scss 中的内容被导入到这里 */ body { background-color: #007bff; }

编译后的 styles2.css

/* _variables.scss 中的内容被导入到这里 */ button { background-color: #6c757d; }

可以看到,styles1.cssstyles2.css 中都包含了 _variables.scss 中定义的样式,而实际上 _variables.scss 中的内容只需要加载一次,然后在多个样式文件中共享。重复加载会增加 CSS 文件的大小,影响性能,并可能导致样式冲突问题。

而使用 @use 导入方式可以避免重复加载问题,因为它会确保每个模块只加载一次,即使在多个文件中导入。这样可以优化性能,并保持样式表的精简和一致性。

命名空间

@import是没有命名空间的,我们来介绍一下@use的命名空间是如何作用的。

1. 不使用as,则直接将文件名当作命名空间

在 SCSS 中,当在 @use 后面直接跟上文件路径,并且没有使用 as 关键字指定命名空间,表示将导入的模块内容整体作为一个命名空间,并且使用被导入文件的名称作为命名空间的标识。

假设有以下两个 SCSS 文件:

文件:_variables.scss

// _variables.scss $primary-color: #007bff; $secondary-color: #6c757d;

文件:styles.scss

// styles.scss @use 'variables.scss'; body { background-color: variables.$primary-color; } button { background-color: variables.$secondary-color; }

在这个示例中,styles.scss 使用 @use 直接导入了 variables.scss 文件,而没有使用 as 关键字指定命名空间。这意味着 _variables.scss 中的所有内容将被合并到 styles.scss 中,并且使用 variables 作为命名空间的标识。

注意,因为 @use 创建了命名空间,所以我们在 styles.scss 中需要使用 variables.$primary-colorvariables.$secondary-color 来访问 _variables.scss 中定义的变量。

2. 使用as xxx,则以后面命名的变量xxx作为命名空间

还是用刚刚的例子,假设有以下两个 SCSS 文件:

文件:_variables.scss

// _variables.scss $primary-color: #007bff; $secondary-color: #6c757d;

文件:styles.scss

// styles.scss @use 'variables.scss' as customVars; body { background-color: customVars.$primary-color; } button { background-color: customVars.$secondary-color; }

在这个示例中,styles.scss 使用 @use 导入了 _variables.scss 文件,并使用 as customVars 为导入的模块创建了一个命名空间 customVars。然后,我们使用 + 后面加上 customVars 来指定变量名作为命名空间的标识。

styles.scss 中,我们可以通过 customVars.$primary-colorcustomVars.$secondary-color 来访问 _variables.scss 中定义的变量。这样的用法可以避免变量冲突,并提供更清晰的命名空间标识,增加代码的可读性。

但是有一种特殊情况,就是通过 as * 来导入

如果在 @use 后面使用 as *,表示将导入的模块的所有内容直接合并到当前文件中,并且不会创建一个命名空间。这样可以让导入的模块的所有变量、mixin、函数等直接在当前文件中使用,而不需要使用命名空间来访问它们。

让我们继续使用上面的示例:

文件:_variables.scss

// _variables.scss $primary-color: #007bff; $secondary-color: #6c757d;

文件:styles.scss

// styles.scss @use 'variables.scss' as *; body { background-color: $primary-color; } button { background-color: $secondary-color; }

在这个示例中,styles.scss 使用 @use 导入了 _variables.scss 文件,并使用 as * 表示导入模块的所有内容,而不为它们创建一个命名空间。

常见的函数使用,@mixin @include @extends @each 等使用

继承(@extends)

@extend 指令告诉 Sass 一个选择器的样式从另一选择器继承。如果一个样式与另外一个样式几乎相同,只有少量的区别,则使用 @extend 就显得很有用

.contanier1{
  font-size: 24px;
  font-weight: bold;
  color: green;
}
.contanier2{ 
  @extend .contanier1;
  color: red;
}
.contanier3{ 
  @extend .contanier1;
  font-size: 30px;
}
---
.contanier1, .contanier3, .contanier2 {
  font-size: 24px;
  font-weight: bold;
  color: green;
}
.contanier2 {
  color: red;
}
.contanier3 {
  font-size: 30px;
}
占位符 % placeholder

它可取代以前 CSS 中的基类造成的代码冗余的情形。 因为 %placeholder 声明的代码,如果不被 @extend 调用的话,不会产生任何代码。

%fz20{
  font-size: 20px;
}
%red{
  color: red;
}
.wrap{
  @extend %fz20;
  @extend %red;
}
.contanier1{
  @extend %fz20;
  .content{
    @extend %red;
  }
}
---
.wrap, .contanier1{
  font-size: 20px;
}
.wrap, .contanier1 .content{
  color: red;
}

如果仅是想提取部分公共的css出来,建议用%**

混入(@mixin)

语法: @mixin name { property: value; property: value; ... }

@mixin link {
  line-height: 36px;
}
@mixin basis-text{
  font-size: 24px;
  font-weight: bold;
  color: green;
  @include link; // 混入中也可以包含混入
}
.contanier1{
  @include basis-text;
}
---
.contanier1 {
  font-size: 24px;
  font-weight: bold;
  color: green;
  line-height: 36px;
}
向混入传递变量
@mixin basis-text($width: 2px,$color: red){
  font-size: 20px;
  color: green;
  border: $width solid $color;
}
.contanier1{
  @include basis-text;
}
.contanier2{ 
  @include basis-text(5px,blue);
}
---
.contanier1 {
  font-size: 20px;
  color: green;
  border: 2px solid red;
}
.contanier2 {
  font-size: 20px;
  color: green;
  border: 5px solid blue;
}
可变参数

有时,不能确定一个混入(mixin)或者一个函数(function)使用多少个参数,这时就可使用 ... 来设置可变参数。 如:创建盒子阴影(box-shadow)的一个混入(mixin)可采取任何数量的 box-shadow 作为参数。

@mixin box-shadow($shadows...) {
   -moz-box-shadow: $shadows;
   -webkit-box-shadow: $shadows;
   box-shadow: $shadows;
}

.shadows {
  @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
}
---
.shadows {
  -moz-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  -webkit-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
}

控制指令

条件语句( @if )

当 @if 的表达式返回值不是 false 或者 null 时,条件成立,输出 {} 内的代码:

p {
  @if 1 + 1 == 2 { border: 1px solid; }
  @if 5 < 3 { border: 2px dotted; }
  @if null  { border: 3px double; }
}
---
p {
  border: 1px solid; 
}
搭配@else if 和@mixin
@mixin txt($weight) { 
  color: white; 
  @if $weight == bold { 
    font-weight: bold;
  } 
  @else if $weight == light { 
    font-weight: 100;
  } 
  @else { 
    font-weight: normal;
  } 
}

.txt1 { 
  @include txt(bold); 
}
---
.txt1 {
  color: white;
  font-weight: bold;
}

循环语句

@for
@for 指令可在限制的范围内重复输出格式,每次按要求(变量的值)对输出结果做出变动。
包含两种格式:@for $var from <start> through <end>,或 @for $var from <start> to <end>;
区别: through 与 to 的含义:当使用 through 时,条件范围包含 <start> 与 <end> 的值,
而使用 to 时条件范围只包含 <start> 的值不包含 <end> 的值。
另外,$var 可以是任何变量,如 $i;<start> 和 <end> 必须是整数值。

@for $i from 1 through 3 {
  .item-#{$i} { width: 2em * $i; }
}
---
.item-1 {
  width: 2em; 
}
.item-2 {
  width: 4em; 
}
.item-3 {
  width: 6em; 
}
@while
@while 指令重复输出格式直到表达式返回结果为 false。这样可以实现比 @for 更复杂的循环,只是很少会用到。

$i: 6;
@while $i > 0 {
  .item-#{$i} { width: 2em * $i; }
  $i: $i - 2;
}
---
.item-6 {
  width: 12em; 
}
.item-4 {
  width: 8em; 
}
.item-2 {
  width: 4em; 
}
@each
@each 指令的格式是 $var in <list>, $var 可以是任何变量名。如 $length 或 $name,而 <list> 是一连串的值,也就是值列表。
@each 将变量 $var 作用于值列表中的每一个项目,然后输出结果。

@each $animal in puma, sea-slug, egret, salamander {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
  }
}
---
.puma-icon {
  background-image: url('/images/puma.png'); 
}
.sea-slug-icon {
  background-image: url('/images/sea-slug.png'); 
}
.egret-icon {
  background-image: url('/images/egret.png'); 
}
.salamander-icon {
  background-image: url('/images/salamander.png'); 
}
// 嵌套
$colors: (
  primary: red,
  success: green,
);
@each $name,$color in $colors {
  .text-#{$name} {
    color: $color;
  }
}
---
.text-primary {
  color: red;
}
.text-success {
  color: green;
}