Sass模块化开发与引入方式

6/10/2021 CSS

在 Sass 中,每个文件被视为一个模块,并且使用 Sass 编译器会将每个模块编译成独立的 CSS 文件。例如,main.scsslist.scss 分别会编译为 main.csslist.css

同时,Sass 采用了以 _ 开头的命名规则,用于将一个文件作为模块引入到另一个文件中。当使用 @import@use@forward 引入文件时,Sass 编译器会将这些文件编译为同一个 CSS 文件。

在 Sass 中每个文件都会认为一个模块,每个模块都被 sass-loader 编译成独立 css 文件。

例如 main.scss, _list.scss → main.css

Note: 所以'_'开头的 scss 文件一般用来定义变量,函数或者是 mixin 函数。

Sass 中引入别的文件的常用的几种方式

  1. @import
  2. @use
  3. @forward
  4. meta.load-css

# @import

使用方式是 @import ‘path/to/filename’,如果有~在 path 的前方,则认为这个文件是根据 webpack 的 alias,再去找对应的文件

如果被引入的文件有''的话,可以省略‘’,例如_filename.scss, 则通过@import 'filename'去引入。

import 在 Sass 中用于导入其他文件的样式。使用方式为 @import 'path/to/filename'。如果在路径前添加了 ~,则 Sass 编译器会将其视为 webpack 别名,并去查找对应文件。

如果被引入的文件的名称以 _ 开头,则可以省略下划线。例如,对于 _filename.scss 文件,可以使用 @import 'filename' 进行引入。

然而,@import 是不被官方推荐的引入方式,因为它存在一些问题:

其一,@import 其实是 css 的标准;

其二,如果多次引入同样文件,会降低编译速度,造成样式冲突和覆盖,生成重复的样式;

其三,如果引入一个同名的函数,则会覆盖当前的函数

其四,无 scope 的概念,例如@import funciton1.scss, function2.scss,并在当前文件调用 abc 的函数,不知道 abc 函数式来自 function1 还是 function2

# @use

@use 是 Sass 官方推荐的模块引入方式,支持作用域的概念。

通过 @use 引入的模块具有独立的作用域,避免了样式冲突问题。

(但如果是用 node-sass 的方式,目前只支持@import)

// src/_corners.scss
$radius: 3px;

@mixin rounded {
  border-radius: $radius;
}

// style.scss
@use 'src/corners';

.button {
  @include corners.rounded;
  padding: 5px + corners.$radius; // corners作为scope去调用,更符合前端人模块化的思维
}

@use 支持 with 操作符,用于修改被引入文件中变量的默认值

// _library.scss
$primary-color: #f8bbd0 !default;
$accent-color: #6a1b9a !default;

.button {
  background-color: $primary-color;
  border: 1px solid $accent-color;
  border-radius: 3px;
}

// style.scss
@use 'library' with (
  $primary-color: #fff,
  $accent-color: #000
);

// 编译成css

.button {
  background-color: #fff;
  border: 1px solid #000;
  border-radius: 3px;
}

# meta.load-css

这个跟@use其实是非常相似的,不同的是要通过@include的方式去引入,具有局部的概念

// dark-theme/_code.scss
$border-contrast: false !default;

code {
  background-color: #6b717f;
  color: #d2e1dd;
  @if $border-contrast {
    border-color: #dadbdf;
  }
}

@use 'sass:meta';

body.dark {
  @include meta.load-css(
    'dark-theme/code',
    $with: ('border-contrast': true)
  ); // 仅在body.dark下生效
}

// 编译成css
CSS OUTPUT body.dark code {
  background-color: #6b717f;
  color: #d2e1dd;
  border-color: #dadbdf;
}

# @forward

作用就如词义—转发,当通过@use的方法进入别的文件时,被引文件里的内容只能在当前文件中使用,第三个文件则使用不了,这时候@forward就可以发挥作用了。

// src/_list.scss
@mixin list-reset {
  margin: 0;
  padding: 0;
  list-style: none;
}

// bootstrap.scss
@forward 'src/list';

// styles.scss
@use 'bootstrap';

li {
  @include bootstrap.list-reset;
}

// 编译成css
li {
  margin: 0;
  padding: 0;
  list-style: none;
}

同时@forward还提供一些方法 hide, as

默认@forward全部变量方法都转发出去, 那么可以通过指定 hide 的方式去隐藏某些不让第三个文件去引用

as的作用就重新指定名称,加前缀等方式,如 @forward "src/list" as abc-*;style.scss就要用bootstrap.abc-list-reset去引用对应的样式。