Appearance
Sass 模块系统
Sass模块系统是Sass 4.0引入的重要功能,旨在替代旧的@import系统,提供更好的性能、作用域隔离和依赖管理。本章将详细介绍Sass模块系统的使用方法和优势。
模块系统概述
Sass模块系统使用@use规则替代传统的@import规则,提供了以下优势:
- 作用域隔离:模块中的变量、函数和混合宏不会污染全局命名空间
- 性能提升:模块只会被加载一次,即使在多个地方使用
- 明确的依赖关系:可以清楚地看到每个文件依赖了哪些模块
@use 规则基础
scss
// _variables.scss - 定义变量模块
$primary-color: #007bff;
$secondary-color: #6c757d;
$font-size-base: 16px;
$border-radius: 4px;
// _functions.scss - 定义函数模块
@function px-to-rem($px, $base: 16px) {
@return ($px / $base) * 1rem;
}
@function calculate-opacity($color, $alpha: 1) {
@return rgba($color, $alpha);
}
// _mixins.scss - 定义混合宏模块
@mixin button-style($bg-color: #007bff, $text-color: white) {
background-color: $bg-color;
color: $text-color;
padding: 0.5rem 1rem;
border: none;
border-radius: $border-radius;
cursor: pointer;
&:hover {
background-color: darken($bg-color, 10%);
}
}
// main.scss - 使用模块
@use 'variables';
@use 'functions';
@use 'mixins';
.element {
color: variables.$primary-color;
font-size: functions.px-to-rem(18px);
.button {
@include mixins.button-style(variables.$secondary-color);
}
}
命名空间和别名
默认命名空间
scss
// _colors.scss
$primary: #007bff;
$secondary: #6c757d;
@function lighten-color($color, $amount: 10%) {
@return lighten($color, $amount);
}
// _typography.scss
$font-family: 'Arial', sans-serif;
$font-size: 16px;
// main.scss
@use 'colors';
@use 'typography';
.card {
background-color: colors.$primary;
color: colors.lighten-color(colors.$primary, 20%);
font-family: typography.$font-family;
font-size: typography.$font-size;
}
使用as关键字设置别名
scss
// 为模块设置简短的别名
@use 'colors' as c;
@use 'typography' as t;
@use 'layout' as l;
.element {
background-color: c.$primary;
font-family: t.$font-family;
padding: l.$standard-spacing;
}
// 避免命名冲突
@use 'button-styles' as btn;
@use 'form-styles' as form;
.submit-btn {
@include btn.button-style;
}
.form-field {
@include form.input-style;
}
顶级命名空间
scss
// 当文件名以_开头时,破折号会转换为驼峰命名
// _component-utils.scss
$default-padding: 1rem;
$default-margin: 0.5rem;
@function calculate-width($columns, $total-columns: 12) {
@return percentage($columns / $total-columns);
}
// main.scss
@use 'component-utils' as utils;
.card {
padding: utils.$default-padding;
width: utils.calculate-width(6);
}
模块成员访问
变量访问
scss
// _theme.scss
// 默认导出所有以$开头的变量
$primary-color: #007bff;
$secondary-color: #6c757d;
$text-color: #333;
// 仅导出特定变量
$_internal-color: #f8f9fa; // 前缀下划线表示私有
$public-color: #28a745;
// 使用变量
@use 'theme';
.card {
background-color: theme.$primary-color;
color: theme.$text-color;
border: 1px solid theme.$secondary-color;
}
函数访问
scss
// _math-helpers.scss
@function fibonacci($n) {
@if $n <= 1 {
@return $n;
}
@return fibonacci($n - 1) + fibonacci($n - 2);
}
@function clamp($value, $min, $max) {
@return if($value < $min, $min, if($value > $max, $max, $value));
}
@function golden-ratio($value, $increment: 1) {
$phi: 1.618033988749895;
@return $value * pow($phi, $increment);
}
// _typography.scss
@use 'math-helpers' as math;
.text {
font-size: math.golden-ratio(1rem, 1);
max-width: math.clamp(100%, 300px, 800px);
}
混合宏访问
scss
// _grid.scss
@mixin container($max-width: 1200px) {
max-width: $max-width;
margin: 0 auto;
padding: 0 1rem;
}
@mixin row {
display: flex;
flex-wrap: wrap;
margin: 0 -0.5rem;
}
@mixin col($width: 1) {
flex: 0 0 percentage($width);
padding: 0 0.5rem;
box-sizing: border-box;
}
// main.scss
@use 'grid';
.main-container {
@include grid.container(1400px);
.content-row {
@include grid.row;
.sidebar {
@include grid.col(0.25); // 25%
}
.main-content {
@include grid.col(0.75); // 75%
}
}
}
模块路径和文件组织
相对路径导入
scss
// 在scss/components/_button.scss中
@use '../abstracts/variables' as vars;
@use '../abstracts/mixins' as mx;
.button {
@include mx.button-style(vars.$primary-color);
padding: vars.$spacing-md;
}
索引文件模式
scss
// scss/helpers/_index.scss (或 _index.scss)
@forward 'color-functions';
@forward 'math-functions';
@forward 'string-helpers';
// scss/helpers/color-functions.scss
@function contrast-color($color) {
@return if(lightness($color) > 50, #000, #fff);
}
@function random-color() {
@return rgb(random(255), random(255), random(255));
}
// main.scss
@use 'helpers' as h;
.element {
color: h.contrast-color(#333);
background-color: h.random-color();
}
@forward 规则
@forward规则允许一个模块转发另一个模块的内容。
基本转发
scss
// _private.scss
$secret-token: 'abc123';
$_internal-setting: 10px;
// _public.scss
@forward 'private'; // 转发所有公共成员
// main.scss
@use 'public';
// 可以访问private模块中的公共变量
.element {
content: public.$secret-token;
}
限制转发内容
scss
// _all-config.scss
$api-url: 'https://api.example.com';
$timeout: 5000ms;
$_debug-mode: true;
$_log-level: 'verbose';
// _safe-config.scss
@forward 'all-config' hide $api-url, $_debug-mode; // 隐藏某些变量
// _admin-config.scss
@forward 'all-config' show $api-url, $timeout; // 只显示特定变量
// 使用限制转发的模块
@use 'safe-config';
// safe-config中不包含$api-url和$_debug-mode
.component {
timeout: safe-config.$timeout; // 可以访问
// api-url: safe-config.$api-url; // 错误:不可访问
}
使用as前缀
scss
// _colors.scss
$primary: #007bff;
$secondary: #6c757d;
// _branding.scss
@forward 'colors' as brand-*; // 添加前缀
// main.scss
@use 'branding';
.element {
color: branding.$brand-primary;
border-color: branding.$brand-secondary;
}
模块配置
使用with配置模块
scss
// _theme.scss
$primary-color: #007bff !default;
$secondary-color: #6c757d !default;
$border-radius: 4px !default;
.button {
background-color: $primary-color;
border-radius: $border-radius;
}
// _custom.scss
@use 'theme' with (
$primary-color: #28a745,
$border-radius: 8px
);
.custom-button {
@include theme.button-style;
// 使用配置后的变量值
}
模块配置最佳实践
scss
// _configurable-component.scss
$padding: 1rem !default;
$background: #f8f9fa !default;
$border-width: 1px !default;
$border-color: #dee2e6 !default;
$border-radius: 4px !default;
@use 'configurable-component' with (
$background: #e9ecef,
$border-color: #adb5bd
);
.component {
padding: configurable-component.$padding;
background-color: configurable-component.$background;
border: configurable-component.$border-width solid configurable-component.$border-color;
border-radius: configurable-component.$border-radius;
}
模块与现有代码的兼容性
混合使用@use和@import
scss
// 推荐:逐步迁移,先使用@use
@use 'new-module';
@use 'another-module';
// 仍然可以使用@import,但不推荐
@import 'legacy-file';
创建兼容性层
scss
// _compatibility.scss - 为旧代码提供兼容性
@use 'modern-theme' as theme;
@use 'modern-layout' as layout;
// 重新导出为全局变量(不推荐,仅用于迁移)
$primary-color: theme.$primary-color;
$grid-columns: layout.$columns;
@function get-primary() {
@return theme.$primary-color;
}
@mixin grid-row {
@include layout.row;
}
实际项目示例
项目结构
scss/
├── abstracts/
│ ├── _variables.scss
│ ├── _functions.scss
│ ├── _mixins.scss
│ └── _placeholders.scss
├── base/
│ ├── _reset.scss
│ ├── _typography.scss
│ └── _utilities.scss
├── components/
│ ├── _buttons.scss
│ ├── _cards.scss
│ └── _forms.scss
├── layouts/
│ ├── _grid.scss
│ ├── _header.scss
│ └── _footer.scss
├── pages/
│ ├── _home.scss
│ └── _about.scss
├── themes/
│ └── _default.scss
└── main.scss
抽象层模块
scss
// scss/abstracts/_variables.scss
// 颜色变量
$colors: (
'primary': #007bff,
'secondary': #6c757d,
'success': #28a745,
'danger': #dc3545,
'warning': #ffc107,
'info': #17a2b8
);
// 间距变量
$spacers: (
0: 0,
1: 0.25rem,
2: 0.5rem,
3: 1rem,
4: 1.5rem,
5: 3rem
);
// 断点变量
$breakpoints: (
'xs': 0,
'sm': 576px,
'md': 768px,
'lg': 992px,
'xl': 1200px,
'xxl': 1400px
);
// scss/abstracts/_functions.scss
@function color($key) {
@return map-get($colors, $key);
}
@function spacer($level) {
@return map-get($spacers, $level);
}
@function breakpoint($key) {
@return map-get($breakpoints, $key);
}
// scss/abstracts/_mixins.scss
@mixin respond-to($breakpoint) {
@media (min-width: breakpoint($breakpoint)) {
@content;
}
}
@mixin button-variant($bg, $color: white) {
background-color: $bg;
color: if(lightness($bg) > 50, #212529, $color);
&:hover {
background-color: darken($bg, 10%);
}
}
主入口文件
scss
// scss/main.scss
// 导入抽象层
@use 'abstracts/variables' as vars;
@use 'abstracts/functions' as func;
@use 'abstracts/mixins' as mx;
// 基础样式
@use 'base/reset';
@use 'base/typography';
@use 'base/utilities';
// 组件样式
@use 'components/buttons';
@use 'components/cards';
@use 'components/forms';
// 布局样式
@use 'layouts/grid';
@use 'layouts/header';
@use 'layouts/footer';
// 页面样式
@use 'pages/home';
@use 'pages/about';
// 使用模块内容
.page-wrapper {
padding: func.spacer(3);
@include mx.respond-to(md) {
padding: func.spacer(4);
}
.primary-button {
@include mx.button-variant(func.color('primary'));
}
}
迁移指南
从@import迁移到@use
scss
// 旧的写法 (@import)
// main.scss
@import 'variables';
@import 'mixins';
@import 'buttons';
// 按钮样式可以直接使用变量和混合宏
.btn {
@include button-style;
background-color: $primary-color;
}
// 新的写法 (@use)
// main.scss
@use 'variables' as vars;
@use 'mixins' as mx;
@use 'buttons';
.btn {
@include mx.button-style;
background-color: vars.$primary-color;
}
创建迁移脚本
scss
// _migration-helper.scss
// 临时帮助迁移的模块
@use 'real-variables' as rv;
@use 'real-mixins' as rm;
// 重新导出以便逐步迁移
$primary-color: rv.$primary-color;
$secondary-color: rv.$secondary-color;
@mixin button-style {
@include rm.button-style;
}
Sass模块系统提供了更好的代码组织方式和作用域管理,是现代Sass开发的推荐方式。