Skip to content

2.sass模块化

概述

Sass引用文件有三种方式,@use, @forward@import。 引用文件时可以省略文件后缀。如果引用文件夹下的 index,可以只写到文件夹。

介绍两个2个专有名词:

  • 代码片段(Partial):文件名以 _ 开头的文件,只有被其他被编译的文件引用才会被编译。
  • 成员(Members):指 variable, mixins, function

@use

通过 @use 引用其它文件,可以使用其中的成员,并合并编译生成的 CSS 文件。 使用成员需要指明来源。

sass
// src/_corner.scss
$radius: 3px;

@mixin rounded {
  border-radius: $radius;
}
sass
// style1.scss 普通引用,使用文件名作为分组
@use "src/corners";

.button {
  @include corners.rounded;
  padding: 5px + corners.$radius;
}
sass
/* style.css */
.button {
  border-radius: 3px;
  padding: 8px;
}

别名

成员自动根据文件名分组。可以给分组添加别名。 如果别名是 *,则不用指明(尽量不要使用)。 编译结果同上。

sass
// style2.scss 使用别名 c
@use "src/corners" as c;

.button {
  @include c.rounded;
  padding: 5px + c.$radius;
}
sass
// style3.scss 别名使用 *
@use "src/corners" as *;

.button {
  @include rounded;
  padding: 5px + $radius;
}

不转发

通过 @use 引用的成员,不能在被引用时使用。

B @use CA @use BA 无法使用 C 的成员。

私有成员

名字以 _ 开头的成员表示私有,通过 @use 无法使用。

配置变量

变量声明后添加 !default 表示支持配置, 通过 @use 引用文件时,使用 with $map 配置被引用文件中支持配置变量的值。

sass
// _library.scss
$black: #000 !default;
$border-radius: 0.25rem !default;
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;

code {
  border-radius: $border-radius;
  box-shadow: $box-shadow;
}
sass
// style.scss
@use 'library' with (
  $black: #222,
  $border-radius: 0.1rem
);
sass
/* style.css */
code {
  border-radius: 0.1rem;
  box-shadow: 0 0.5rem 1rem rgba(34, 34, 34, 0.15);
}

@forward

@forward 转发被引用文件内部的成员,自身不能使用。编译后的 CSS 会与被引用文件编译结果合并。

添加前缀

当转发多个文件时,为了区分来源,避免混乱和命名冲突,通过 as 给成员添加前缀。

A @use BB @forward C1, C2A 中可以通过 B.member 使用 C1, C2 中定义的成员。 但是无法区分 B.member 来自 C1 还是 C2。 为了避免混乱和命名冲突,使用 as 给引用文件中的成员添加前缀。

sass
// src/_list.scss
@mixin reset {
  margin: 0;
  padding: 0;
  list-style: none;
}
sass
// bootstrap.scss
@forward "src/list" as list-*;
sass
// styles.scss
@use "bootstrap";

li {
  @include bootstrap.list-reset;
}
sass
/* styles.css */
li {
  margin: 0;
  padding: 0;
  list-style: none;
}

可控

通过 showhide 手动控制转发的成员。

sass
// src/_list.scss
$horizontal-list-gap: 2em;

@mixin list-reset {
  margin: 0;
  padding: 0;
  list-style: none;
}

@mixin list-horizontal {
  @include reset;

  li {
    display: inline-block;
    margin: {
      left: -2px;
      right: $horizontal-list-gap;
    }
  }
}
sass
// bootstrap.scss
@forward "src/list" hide list-reset, $horizontal-list-gap;

私有成员

支持私有成员,私有成员不会转发。

配置变量

@use。转发后的可配变量依然可以再次配置。

sass
// _library.scss
$black: #000 !default;
$border-radius: 0.25rem !default;
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;

code {
  border-radius: $border-radius;
  box-shadow: $box-shadow;
}
sass
// _opinionated.scss
@forward 'library' with (
$black: #222 !default,
$border-radius: 0.1rem !default
);
sass
// style.scss
@use 'opinionated' with ($black: #333);

@use 与 @forward 合并使用

如果一个模块同时需要使用和转发另一个模块,应该通过 @forward@use 各引用一次,不会多次编译,最终生成的 CSS 不会重复。

@forward 应先于 @use,否则特殊情况下会出错。 比如:C 中含有可配变量,B @use & @forward CA @use B。 如果 B@use 先于 @forward,在 A 中使用 with 配置变量会报错。

@import

既可使用被引用文件的成员,也可以转发,甚至之后引用的文件中也可以使用。 A @import B, C,在 C 中也可使用 B 中的成员。

可一次引用多个模块,模块间以逗号分割。

编译结果会合并,每次引用都会编译,多次引用会造成冗余 CSS

嵌套

@import 不用写在顶部,甚至可以被嵌套在选择器中。 这样被引用文件编译生成的 CSS 都在选择器内部。 但是被引用文件的成员仍然是全局可用的。

被引用文件内部使用父选择器,则父选择器包括 @import 的父选择器。

CSS @import 区分

Sass @import 最终会生成 CSS 代码。而 CSS @import 不变。 下面4种情况,当作 CSS 处理,不会被编译。

  1. url.css 结尾。
  2. urlhttp(s):// 开头。
  3. urlurl() 包裹。
  4. 媒体查询

缺陷

  1. 使用成员无法区分来源,来自自己定义还是某个引用文件。
  2. 成员都是全局的,容易发生命名冲突。
  3. @extend 无法预测继承的内容来自何处。
  4. 每次引用都会编译,延长编译时间和产生冗余 CSS
  5. 不支持私有成员和 placeholder selectors(两个都是减少冗余代码的手段)。

Sass 准备淘汰 @import,尽量使用 @use 替代。

对比

区别

特性@use@forward@import
支持私有成员✔️✔️
可配置变量✔️✔️
使用引用的成员✔️✔️
转发引用的成员✔️✔️
合并编译结果✔️✔️✔️
多次引用一次编译✔️✔️

适用场景

  • 如果编译器为 node-sass 或其他不支持 @use@forward 的编译器,只能使用 @import
  • 需要使用被引用文件中的成员,使用 @use
  • 需要转发被引用文件中的成员,使用 @forward
  • 既需要使用,有需要转发被引用文件中的成员,同时使用 @forward@use,注意先使用 @forward

made with ❤️ by ankang