2.sass模块化
概述
Sass引用文件有三种方式,@use, @forward 和 @import。 引用文件时可以省略文件后缀。如果引用文件夹下的 index,可以只写到文件夹。
介绍两个2个专有名词:
- 代码片段(
Partial):文件名以_开头的文件,只有被其他被编译的文件引用才会被编译。 - 成员(
Members):指variable, mixins, function。
@use
通过 @use 引用其它文件,可以使用其中的成员,并合并编译生成的 CSS 文件。 使用成员需要指明来源。
// src/_corner.scss
$radius: 3px;
@mixin rounded {
border-radius: $radius;
}// style1.scss 普通引用,使用文件名作为分组
@use "src/corners";
.button {
@include corners.rounded;
padding: 5px + corners.$radius;
}/* style.css */
.button {
border-radius: 3px;
padding: 8px;
}别名
成员自动根据文件名分组。可以给分组添加别名。 如果别名是 *,则不用指明(尽量不要使用)。 编译结果同上。
// style2.scss 使用别名 c
@use "src/corners" as c;
.button {
@include c.rounded;
padding: 5px + c.$radius;
}// style3.scss 别名使用 *
@use "src/corners" as *;
.button {
@include rounded;
padding: 5px + $radius;
}不转发
通过 @use 引用的成员,不能在被引用时使用。
B @use C,A @use B。A 无法使用 C 的成员。
私有成员
名字以 _ 开头的成员表示私有,通过 @use 无法使用。
配置变量
变量声明后添加 !default 表示支持配置, 通过 @use 引用文件时,使用 with $map 配置被引用文件中支持配置变量的值。
// _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;
}// style.scss
@use 'library' with (
$black: #222,
$border-radius: 0.1rem
);/* 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 B,B @forward C1, C2。 A 中可以通过 B.member 使用 C1, C2 中定义的成员。 但是无法区分 B.member 来自 C1 还是 C2。 为了避免混乱和命名冲突,使用 as 给引用文件中的成员添加前缀。
// src/_list.scss
@mixin reset {
margin: 0;
padding: 0;
list-style: none;
}// bootstrap.scss
@forward "src/list" as list-*;// styles.scss
@use "bootstrap";
li {
@include bootstrap.list-reset;
}/* styles.css */
li {
margin: 0;
padding: 0;
list-style: none;
}可控
通过 show 和 hide 手动控制转发的成员。
// 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;
}
}
}// bootstrap.scss
@forward "src/list" hide list-reset, $horizontal-list-gap;私有成员
支持私有成员,私有成员不会转发。
配置变量
同 @use。转发后的可配变量依然可以再次配置。
// _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;
}// _opinionated.scss
@forward 'library' with (
$black: #222 !default,
$border-radius: 0.1rem !default
);// style.scss
@use 'opinionated' with ($black: #333);@use 与 @forward 合并使用
如果一个模块同时需要使用和转发另一个模块,应该通过 @forward 和 @use 各引用一次,不会多次编译,最终生成的 CSS 不会重复。
@forward 应先于 @use,否则特殊情况下会出错。 比如:C 中含有可配变量,B @use & @forward C,A @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 处理,不会被编译。
url以.css结尾。url以http(s)://开头。url被url()包裹。- 媒体查询
缺陷
- 使用成员无法区分来源,来自自己定义还是某个引用文件。
- 成员都是全局的,容易发生命名冲突。
@extend无法预测继承的内容来自何处。- 每次引用都会编译,延长编译时间和产生冗余
CSS。 - 不支持私有成员和
placeholder selectors(两个都是减少冗余代码的手段)。
Sass 准备淘汰 @import,尽量使用 @use 替代。
对比
区别
| 特性 | @use | @forward | @import |
|---|---|---|---|
| 支持私有成员 | ✔️ | ✔️ | ❌ |
| 可配置变量 | ✔️ | ✔️ | ❌ |
| 使用引用的成员 | ✔️ | ❌ | ✔️ |
| 转发引用的成员 | ❌ | ✔️ | ✔️ |
| 合并编译结果 | ✔️ | ✔️ | ✔️ |
| 多次引用一次编译 | ✔️ | ✔️ | ❌ |
适用场景
- 如果编译器为
node-sass或其他不支持@use和@forward的编译器,只能使用@import - 需要使用被引用文件中的成员,使用
@use - 需要转发被引用文件中的成员,使用
@forward - 既需要使用,有需要转发被引用文件中的成员,同时使用
@forward和@use,注意先使用@forward。
