SCSS(Sass)提供了强大的模块系统来组织和管理样式代码。本文将详细介绍三个核心指令:@import
、@use
和 @forward
,帮助你构建更好的样式架构。
目录
- @import - 传统的导入方式
- @use - 现代模块系统
- @forward - 模块转发
- 最佳实践
- 迁移指南
@import - 传统的导入方式
基本语法
@import "path/to/file";
@import "file1", "file2", "file3";
@import url("https://fonts.googleapis.com/css2?family=Roboto");
特点
- 全局作用域:导入的所有变量、混合器、函数都变成全局可用
- 重复导入问题:同一文件可能被多次导入,导致 CSS 重复
- 命名冲突:没有命名空间,容易产生变量名冲突
示例
// _variables.scss
$primary-color: #007bff;
$font-size: 16px;
// _mixins.scss
@mixin button-style {
padding: 10px 20px;
border-radius: 4px;
}
// main.scss
@import "variables";
@import "mixins";
.button {
@include button-style;
background-color: $primary-color;
font-size: $font-size;
}
问题与限制
// 问题示例:命名冲突
// _theme1.scss
$color: red;
// _theme2.scss
$color: blue;
// main.scss
@import "theme1";
@import "theme2";
// $color 现在是 blue,theme1 的值被覆盖了
@use - 现代模块系统
基本语法
@use "path/to/file";
@use "path/to/file" as namespace;
@use "path/to/file" as *;
@use "path/to/file" with (
$variable: value
);
核心特性
1. 命名空间
// _colors.scss
$primary: #007bff;
$secondary: #6c757d;
@function lighten-color($color, $amount) {
@return lighten($color, $amount);
}
// main.scss
@use "colors";
.button {
background-color: colors.$primary;
border-color: colors.lighten-color(colors.$primary, 20%);
}
2. 自定义命名空间
// 使用自定义命名空间
@use "colors" as c;
.button {
background-color: c.$primary;
}
// 使用通配符导入到全局
@use "colors" as *;
.button {
background-color: $primary; // 直接使用,无需命名空间
}
3. 配置变量
// _theme.scss
$base-font-size: 16px !default;
$primary-color: #007bff !default;
.text {
font-size: $base-font-size;
color: $primary-color;
}
// main.scss
@use "theme" with (
$base-font-size: 18px,
$primary-color: #28a745
);
4. 私有成员
// _utils.scss
$_private-var: "This is private";
$public-var: "This is public";
@function _private-function() {
@return $_private-var;
}
@function public-function() {
@return $public-var;
}
// main.scss
@use "utils";
.test {
// content: utils.$public-var; ✓ 可以访问
// content: utils.$_private-var; ✗ 错误:私有变量不可访问
// content: utils.public-function(); ✓ 可以访问
// content: utils._private-function(); ✗ 错误:私有函数不可访问
}
高级用法
条件导入
// 根据条件导入不同模块
@use "sass:meta";
@if meta.feature-exists("at-error") {
@use "modern-utils";
} @else {
@use "legacy-utils";
}
动态配置
// _config.scss
$theme: "light" !default;
$breakpoints: (
"sm": 576px,
"md": 768px,
"lg": 992px,
) !default;
// main.scss
@use "config" with (
$theme: "dark",
$breakpoints: (
"sm": 480px,
"md": 768px,
"lg": 1024px,
"xl": 1200px,
)
);
@forward - 模块转发
基本概念
@forward
允许一个模块加载另一个模块的成员,并将这些成员作为自己 API 的一部分导出。
基本语法
@forward "path/to/file";
@forward "path/to/file" hide $var1, function1;
@forward "path/to/file" show $var1, $var2;
@forward "path/to/file" as prefix-*;
@forward "path/to/file" with (
$variable: value
);
实际应用场景
1. 创建统一入口文件
// _variables.scss
$primary-color: #007bff;
$secondary-color: #6c757d;
// _mixins.scss
@mixin button {
padding: 10px 20px;
border-radius: 4px;
}
@mixin card {
border: 1px solid #dee2e6;
border-radius: 8px;
}
// _functions.scss
@function rem($pixels) {
@return #{$pixels / 16}rem;
}
// index.scss - 统一入口
@forward "variables";
@forward "mixins";
@forward "functions";
// main.scss - 使用者只需导入一个文件
@use "index" as theme;
.button {
@include theme.button;
background-color: theme.$primary-color;
font-size: theme.rem(16);
}
2. 选择性转发
// _internal.scss
$_internal-var: "secret";
$public-var: "visible";
$debug-var: "debug-info";
@function _internal-helper() {
/* ... */
}
@function public-helper() {
/* ... */
}
@function debug-helper() {
/* ... */
}
// _public-api.scss
// 只转发公共API,隐藏内部实现和调试工具
@forward "internal" hide $_internal-var, _internal-helper, $debug-var, debug-helper;
// 或者使用 show 明确指定要转发的成员
// @forward 'internal' show $public-var, public-helper;
3. 添加前缀避免冲突
// _bootstrap-vars.scss
$primary: #007bff;
$secondary: #6c757d;
// _material-vars.scss
$primary: #2196f3;
$surface: #ffffff;
// _unified-theme.scss
@forward "bootstrap-vars" as bs-*;
@forward "material-vars" as md-*;
// main.scss
@use "unified-theme" as theme;
.bootstrap-button {
background-color: theme.$bs-primary;
}
.material-button {
background-color: theme.$md-primary;
}
4. 配置转发
// _base-theme.scss
$font-family: "Helvetica Neue" !default;
$base-font-size: 16px !default;
$line-height: 1.5 !default;
// _dark-theme.scss
@forward "base-theme" with (
$font-family: "Roboto",
$base-font-size: 14px
);
// 添加暗色主题特定的变量
$background-color: #1a1a1a;
$text-color: #ffffff;
// main.scss
@use "dark-theme";
复杂示例:构建设计系统
// design-system/
// ├── tokens/
// │ ├── _colors.scss
// │ ├── _typography.scss
// │ ├── _spacing.scss
// │ └── index.scss
// ├── components/
// │ ├── _button.scss
// │ ├── _card.scss
// │ └── index.scss
// └── index.scss
// tokens/_colors.scss
$blue-50: #e3f2fd;
$blue-500: #2196f3;
$blue-900: #0d47a1;
$primary: $blue-500 !default;
$primary-light: $blue-50 !default;
$primary-dark: $blue-900 !default;
// tokens/_typography.scss
$font-family-base: "Roboto", sans-serif !default;
$font-size-base: 16px !default;
$font-weight-normal: 400 !default;
$font-weight-bold: 700 !default;
// tokens/_spacing.scss
$spacing-xs: 4px;
$spacing-sm: 8px;
$spacing-md: 16px;
$spacing-lg: 24px;
$spacing-xl: 32px;
// tokens/index.scss
@forward "colors";
@forward "typography";
@forward "spacing";
// components/_button.scss
@use "../tokens" as tokens;
.button {
font-family: tokens.$font-family-base;
font-size: tokens.$font-size-base;
font-weight: tokens.$font-weight-bold;
padding: tokens.$spacing-sm tokens.$spacing-md;
background-color: tokens.$primary;
color: white;
border: none;
border-radius: 4px;
&:hover {
background-color: tokens.$primary-dark;
}
}
// components/index.scss
@forward "button";
@forward "card";
// design-system/index.scss
@forward "tokens";
@forward "components";
// 最终使用
// app.scss
@use "design-system" with (
$primary: #ff5722,
$font-family-base: "Inter"
);
最佳实践
1. 文件组织结构
styles/
├── abstracts/
│ ├── _variables.scss
│ ├── _functions.scss
│ ├── _mixins.scss
│ └── index.scss
├── base/
│ ├── _reset.scss
│ ├── _typography.scss
│ └── index.scss
├── components/
│ ├── _button.scss
│ ├── _card.scss
│ └── index.scss
├── layout/
│ ├── _header.scss
│ ├── _sidebar.scss
│ └── index.scss
└── main.scss
2. 命名约定
// 使用语义化的命名空间
@use "abstracts" as abs;
@use "components" as comp;
@use "layout" as layout;
// 私有成员使用下划线前缀
$_private-variable: value;
@function _private-function() {
/* ... */
}
// 使用 !default 标记可配置变量
$primary-color: #007bff !default;
3. 避免深度嵌套
// ✗ 避免
@use "level1" as l1;
// level1 内部又 @use 了很多其他模块
// ✓ 推荐:使用 @forward 创建扁平的API
@forward "level1";
@forward "level2";
@forward "level3";
4. 性能优化
// 只导入需要的成员
@use "large-library" as lib;
// 只使用 lib.$specific-variable 而不是全部导入
// 使用条件导入
@use "sass:meta";
@if meta.module-exists("optional-feature") {
@use "optional-feature";
}
迁移指南
从 @import 到 @use 的迁移步骤
1. 分析依赖关系
// 原始代码
@import "variables";
@import "mixins";
@import "functions";
// 迁移后
@use "variables" as vars;
@use "mixins" as mix;
@use "functions" as fn;
2. 更新变量引用
// 原始代码
.button {
color: $primary-color;
@include button-style;
font-size: calculate-rem(16);
}
// 迁移后
.button {
color: vars.$primary-color;
@include mix.button-style;
font-size: fn.calculate-rem(16);
}
3. 处理循环依赖
// 使用 @forward 解决循环依赖
// _api.scss
@forward "variables";
@forward "mixins";
@forward "functions";
// main.scss
@use "api";
4. 渐进式迁移
// 可以在同一项目中混用,但要避免同时导入同一文件
@import "legacy-file"; // 旧的导入方式
@use "new-file" as new; // 新的导入方式
总结
特性 | @import | @use | @forward |
---|---|---|---|
命名空间 | ✗ | ✓ | ✓ |
重复导入保护 | ✗ | ✓ | ✓ |
配置变量 | ✗ | ✓ | ✓ |
私有成员 | ✗ | ✓ | ✓ |
性能 | 较差 | 良好 | 良好 |
推荐使用 | ✗ | ✓ | ✓ |
选择指南
- @use:在需要使用其他模块的功能时使用
- @forward:在创建 API 入口或重新导出模块时使用
- @import:仅在处理遗留代码或 CSS 文件时使用
通过合理使用这三个指令,你可以构建出更加模块化、可维护和高性能的 SCSS 代码架构。建议在新项目中完全采用 @use
和 @forward
,逐步将现有项目从 @import
迁移过来。