Skip to content
On this page

Sass 团队协作

在团队环境中使用Sass需要建立明确的协作规范和最佳实践,以确保代码的一致性、可维护性和开发效率。本章将详细介绍Sass团队协作的各个方面。

代码规范与风格指南

命名规范

scss
// 1. 变量命名 - 使用连字符分隔
// 颜色变量
$primary-color: #007bff;
$secondary-text-color: #6c757d;
$success-bg-color: #d4edda;

// 尺寸变量
$base-font-size: 16px;
$border-radius-sm: 2px;
$border-radius-md: 4px;
$border-radius-lg: 8px;

// 间距变量
$spacing-xs: 0.25rem;
$spacing-sm: 0.5rem;
$spacing-md: 1rem;
$spacing-lg: 1.5rem;
$spacing-xl: 3rem;

// 2. 混合宏命名 - 使用连字符分隔,动词开头
@mixin center-element {
  display: flex;
  justify-content: center;
  align-items: center;
}

@mixin responsive-font($min-size, $max-size) {
  font-size: $min-size;
  
  @media (min-width: 768px) {
    font-size: $max-size;
  }
}

// 3. 占位符选择器命名 - 使用%前缀,语义化命名
%button-base {
  padding: 0.5rem 1rem;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

%form-element-base {
  width: 100%;
  padding: 0.75rem;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 1rem;
}

// 4. BEM方法论命名
.card {
  // 组件容器
  background: white;
  border-radius: 8px;
  
  &__header {
    // 组件元素
    padding: 1rem;
    border-bottom: 1px solid #eee;
  }
  
  &__title {
    // 组件元素
    margin: 0;
    font-size: 1.25rem;
  }
  
  &__body {
    // 组件元素
    padding: 1rem;
  }
  
  &__footer {
    // 组件元素
    padding: 1rem;
    border-top: 1px solid #eee;
  }
  
  &--featured {
    // 组件修饰符
    border: 2px solid #007bff;
  }
  
  &--compact {
    // 组件修饰符
    padding: 0.5rem;
  }
}

代码组织结构

scss
// _component-name.scss - 单个组件文件结构示例
// 1. 导入依赖(如果需要)
@use '../abstracts/variables' as vars;
@use '../abstracts/mixins' as mx;

// 2. 组件特定变量(以组件名前缀)
$button-primary-bg: vars.$primary-color;
$button-primary-color: vars.$white;
$button-padding: 0.5rem 1rem;

// 3. 组件特定混合宏
@mixin button-size($padding) {
  padding: $padding;
  font-size: 1rem;
}

// 4. 组件样式
.button {
  @include mx.button-size($button-padding);
  background-color: $button-primary-bg;
  color: $button-primary-color;
  border: none;
  border-radius: vars.$border-radius-md;
  cursor: pointer;
  
  &:hover {
    background-color: vars.darken($button-primary-bg, 10%);
  }
  
  &--secondary {
    background-color: vars.$secondary-color;
    color: vars.$white;
  }
  
  &--large {
    @include mx.button-size(0.75rem 1.5rem);
    font-size: 1.25rem;
  }
}

项目结构规范

推荐的项目结构

scss
// 标准Sass项目结构
/*
scss/
├── abstracts/              # 抽象层 - 变量、函数、混合宏
│   ├── _variables.scss    # 全局变量
│   ├── _functions.scss    # 全局函数
│   ├── _mixins.scss       # 全局混合宏
│   └── _placeholders.scss # 全局占位符
├── base/                  # 基础层 - 重置、排版、通用样式
│   ├── _reset.scss        # 样式重置
│   ├── _typography.scss   # 排版样式
│   └── _helpers.scss      # 辅助类
├── components/            # 组件层 - 独立UI组件
│   ├── _buttons.scss      # 按钮组件
│   ├── _cards.scss        # 卡片组件
│   └── _forms.scss        # 表单组件
├── layout/                # 布局层 - 页面布局组件
│   ├── _header.scss       # 页眉
│   ├── _footer.scss       # 页脚
│   └── _navigation.scss   # 导航
├── pages/                 # 页面层 - 特定页面样式
│   ├── _home.scss         # 首页
│   └── _about.scss        # 关于页
├── themes/                # 主题层 - 主题相关样式
│   └── _default.scss      # 默认主题
└── main.scss              # 主入口文件
*/

// main.scss - 主入口文件
// 1. 抽象层(无输出)
@use 'abstracts/variables';
@use 'abstracts/functions';
@use 'abstracts/mixins';
@use 'abstracts/placeholders';

// 2. 基础层(少量输出)
@use 'base/reset';
@use 'base/typography';
@use 'base/helpers';

// 3. 布局层(结构输出)
@use 'layout/header';
@use 'layout/footer';
@use 'layout/navigation';

// 4. 组件层(组件输出)
@use 'components/buttons';
@use 'components/cards';
@use 'components/forms';

// 5. 页面层(特定页面输出)
@use 'pages/home';
@use 'pages/about';

// 6. 主题层(覆盖样式)
@use 'themes/default';

文件组织最佳实践

scss
// abstracts/_variables.scss
// 颜色变量
$colors: (
  'primary': #007bff,
  'secondary': #6c757d,
  'success': #28a745,
  'danger': #dc3545,
  'warning': #ffc107,
  'info': #17a2b8,
  'light': #f8f9fa,
  'dark': #333
);

// 间距变量
$spacers: (
  0: 0,
  1: 0.25rem,
  2: 0.5rem,
  3: 1rem,
  4: 1.5rem,
  5: 3rem
);

// 断点变量
$grid-breakpoints: (
  'xs': 0,
  'sm': 576px,
  'md': 768px,
  'lg': 992px,
  'xl': 1200px,
  'xxl': 1400px
);

// 字体变量
$font-family-sans-serif: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
$font-size-base: 1rem;
$font-weight-normal: 400;
$font-weight-bold: 700;

// 尺寸变量
$border-width: 1px;
$border-color: #dee2e6;
$border-radius: 0.25rem;
$border-radius-lg: 0.3rem;
$border-radius-sm: 0.2rem;

协作工具与配置

代码格式化配置

json
// .editorconfig
root = true

[*.scss]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.sass]
indent_size = 2
json
// .stylelintrc.json
{
  "extends": ["stylelint-config-standard-scss"],
  "plugins": ["stylelint-scss"],
  "rules": {
    "indentation": 2,
    "string-quotes": "single",
    "no-duplicate-selectors": true,
    "color-hex-case": "lower",
    "color-hex-length": "short",
    "selector-max-id": 0,
    "selector-combinator-space-after": "always",
    "declaration-colon-space-before": "never",
    "declaration-colon-space-after": "always",
    "block-opening-brace-space-before": "always",
    "block-closing-brace-newline-after": [
      "always",
      {
        "ignoreAtRules": ["if", "else"]
      }
    ],
    "scss/at-extend-no-missing-placeholder": true,
    "scss/dollar-variable-colon-space-before": "never",
    "scss/dollar-variable-colon-space-after": "always",
    "scss/selector-no-redundant-nesting-selector": true
  }
}
json
// package.json - 开发脚本
{
  "scripts": {
    "lint:css": "stylelint \"src/scss/**/*.scss\"",
    "lint:css:fix": "stylelint \"src/scss/**/*.scss\" --fix",
    "format": "prettier --write \"src/scss/**/*.scss\"",
    "build:css": "sass src/scss/main.scss dist/css/main.css --style=compressed",
    "watch:css": "sass src/scss/main.scss dist/css/main.css --watch"
  },
  "devDependencies": {
    "stylelint": "^15.0.0",
    "stylelint-config-standard-scss": "^8.0.0",
    "prettier": "^2.8.0"
  }
}

提交规范

javascript
// commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      [
        'feat', // 新功能
        'fix', // 修复
        'docs', // 文档
        'style', // 格式(不影响代码运行的变动)
        'refactor', // 重构(既不修复bug也不添加功能)
        'perf', // 性能优化
        'test', // 测试
        'chore' // 构建过程或辅助工具的变动
      ]
    ],
    'scope-enum': [
      2,
      'always',
      [
        'sass',
        'css',
        'styles',
        'components',
        'layout',
        'base',
        'abstracts',
        'themes'
      ]
    ]
  }
};

代码审查指南

审查清单

scss
// 代码审查检查清单示例
/*
SASS CODE REVIEW CHECKLIST:

1. 命名规范
   - [ ] 变量命名清晰、一致
   - [ ] 混合宏命名描述性
   - [ ] 选择器命名遵循BEM或类似规范
   - [ ] 避免过长的选择器链

2. 代码结构
   - [ ] 文件结构遵循约定
   - [ ] 逻辑分组合理
   - [ ] 注释清晰有用
   - [ ] 避免深度嵌套

3. 性能考虑
   - [ ] 避免不必要的继承
   - [ ] 合理使用混合宏
   - [ ] CSS输出优化
   - [ ] 响应式设计高效

4. 可维护性
   - [ ] 代码易于理解
   - [ ] 功能模块化
   - [ ] 重复代码已抽象
   - [ ] 变量和函数可重用
*/

// 好的代码示例
@use 'abstracts/variables' as vars;
@use 'abstracts/mixins' as mx;

// 清晰的组件结构
.card {
  background-color: vars.$white;
  border: vars.$border-width solid vars.$border-color;
  border-radius: vars.$border-radius;
  
  &__header {
    padding: vars.$spacing-md;
    border-bottom: vars.$border-width solid vars.$border-color;
  }
  
  &__body {
    padding: vars.$spacing-md;
  }
  
  &__footer {
    padding: vars.$spacing-md;
    border-top: vars.$border-width solid vars.$border-color;
  }
}

// 需要改进的代码示例(注释说明)
.bad-example {
  // 避免:过深嵌套
  .level1 {
    .level2 {
      .level3 {
        .level4 {
          // 这种嵌套过深,应使用更清晰的类名
          color: red;
        }
      }
    }
  }
  
  // 避免:生成冗长选择器
  .duplicate-style {
    // 应该使用占位符或混合宏
    padding: 1rem;
    border: 1px solid #ccc;
    border-radius: 4px;
  }
}

文档与注释规范

代码注释标准

scss
// 1. 文件头部注释
/*
 * 组件: 按钮组件
 * 功能: 定义各种按钮样式
 * 作者: 团队A
 * 日期: 2023-01-01
 * 版本: 1.0.0
 */

// 2. 函数/混合宏文档注释
/**
 * 响应式字体大小混合宏
 * 根据屏幕尺寸调整字体大小
 * 
 * @param {Number} $min-size - 最小屏幕下的字体大小
 * @param {Number} $max-size - 最大屏幕下的字体大小  
 * @param {Number} $min-width - 最小屏幕宽度 (默认: 320px)
 * @param {Number} $max-width - 最大屏幕宽度 (默认: 1200px)
 * 
 * @example
 *   @include responsive-font(14px, 18px);
 */
@mixin responsive-font($min-size, $max-size, $min-width: 320px, $max-width: 1200px) {
  font-size: $min-size;
  
  @media (min-width: $min-width) {
    font-size: calc(#{$min-size} + (#{$max-size} - #{$min-size}) * ((100vw - #{$min-width}) / (#{$max-width} - #{$min-width})));
  }
  
  @media (min-width: $max-width) {
    font-size: $max-size;
  }
}

// 3. 复杂逻辑注释
.button-group {
  display: flex;
  
  // 垂直居中对齐按钮
  align-items: center;
  
  // 水平分布按钮,使用flex-grow填充剩余空间
  .button {
    flex: 1;
    
    &:not(:first-child) {
      // 第一个按钮不需要左边距
      margin-left: 0.25rem;
    }
  }
}

// 4. 临时解决方案注释
.feature-in-progress {
  // TODO: 实现完整的响应式行为
  // FIXME: 修复在小屏幕上的布局问题
  // HACK: 临时解决方案,需要重构
  display: block;
}

// 5. 业务逻辑注释
.payment-form {
  // 根据支付类型显示不同样式
  // 信用卡: 蓝色主题
  // 借记卡: 绿色主题  
  // PayPal: 黄色主题
  @if $payment-type == 'credit' {
    background-color: #007bff;
  } @else if $payment-type == 'debit' {
    background-color: #28a745;
  }
}

工作流程与协作

Git工作流程

bash
# Git分支命名规范
# feature/sass-component-name - 新功能分支
# bugfix/sass-issue-description - 修复分支  
# hotfix/sass-urgent-fix - 紧急修复分支
# release/sass-version - 发布分支

# 示例分支操作
git checkout -b feature/sass-button-component
# 开发组件
git add .
git commit -m "feat(sass): add button component with variants"
git push origin feature/sass-button-component
# 创建Pull Request

变量管理协作

scss
// abstracts/_variables.scss - 团队协作变量管理
// 1. 颜色系统
// 品牌颜色
$brand-primary: #007bff !default;
$brand-secondary: #6c757d !default;
$brand-success: #28a745 !default;
$brand-info: #17a7b8 !default;
$brand-warning: #ffc107 !default;
$brand-danger: #dc3545 !default;
$brand-light: #f8f9fa !default;
$brand-dark: #343a40 !default;

// 中性色
$gray-100: #f8f9fa !default;
$gray-200: #e9ecef !default;
$gray-300: #dee2e6 !default;
$gray-400: #ced4da !default;
$gray-500: #adb5bd !default;
$gray-600: #6c757d !default;
$gray-700: #495057 !default;
$gray-800: #343a40 !default;
$gray-900: #212529 !default;

// 2. 间距系统
$spacer: 1rem !default;
$spacers: (
  0: 0,
  1: $spacer * 0.25,
  2: $spacer * 0.5,
  3: $spacer,
  4: $spacer * 1.5,
  5: $spacer * 3,
  6: $spacer * 4,
  7: $spacer * 6,
  8: $spacer * 8
) !default;

// 3. 断点系统
$grid-breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px,
  xxl: 1400px
) !default;

// 4. 容器最大宽度
$container-max-widths: (
  sm: 540px,
  md: 720px,
  lg: 960px,
  xl: 1140px,
  xxl: 1320px
) !default;

团队开发最佳实践

组件开发规范

scss
// components/_component-template.scss - 组件开发模板
// 1. 导入依赖
@use '../abstracts/variables' as vars;
@use '../abstracts/mixins' as mx;

// 2. 组件特定变量(使用组件前缀)
$component-name-padding: vars.$spacing-md !default;
$component-name-bg-color: vars.$white !default;
$component-name-border-color: vars.$gray-300 !default;

// 3. 组件特定混合宏(如需要)
@mixin component-name-variant($bg-color, $text-color: vars.$white) {
  background-color: $bg-color;
  color: $text-color;
  
  &:hover {
    background-color: vars.darken($bg-color, 10%);
  }
}

// 4. 主组件样式
.component-name {
  padding: $component-name-padding;
  background-color: $component-name-bg-color;
  border: vars.$border-width solid $component-name-border-color;
  border-radius: vars.$border-radius;
  
  // 子元素
  &__header {
    font-weight: vars.$font-weight-bold;
    margin-bottom: vars.$spacing-sm;
  }
  
  &__body {
    // 内容区域样式
  }
  
  &__footer {
    margin-top: vars.$spacing-md;
    padding-top: vars.$spacing-sm;
    border-top: vars.$border-width solid $component-name-border-color;
  }
  
  // 修饰符
  &--large {
    padding: vars.$spacing-lg;
  }
  
  &--compact {
    padding: vars.$spacing-sm;
  }
  
  &--primary {
    @include component-name-variant(vars.$brand-primary);
  }
  
  &--secondary {
    @include component-name-variant(vars.$brand-secondary);
  }
}

// 5. 响应式变体(如需要)
@include mx.respond-above(md) {
  .component-name {
    &--responsive {
      // 响应式特定样式
    }
  }
}

代码复用与抽象

scss
// abstracts/_mixins.scss - 团队共享混合宏
// 1. 响应式工具混合宏
@mixin respond-above($breakpoint) {
  @media (min-width: map-get(vars.$grid-breakpoints, $breakpoint)) {
    @content;
  }
}

@mixin respond-below($breakpoint) {
  @media (max-width: map-get(vars.$grid-breakpoints, $breakpoint) - 1px) {
    @content;
  }
}

@mixin respond-between($lower, $upper) {
  @media (min-width: map-get(vars.$grid-breakpoints, $lower)) and (max-width: map-get(vars.$grid-breakpoints, $upper) - 1px) {
    @content;
  }
}

// 2. 布局工具混合宏
@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

@mixin absolute-center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

// 3. 视觉工具混合宏
@mixin text-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@mixin box-shadow($level: 1) {
  @if $level == 1 {
    box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
  } @else if $level == 2 {
    box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
  } @else if $level == 3 {
    box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
  }
}

// 4. 动画混合宏
@mixin transition($property: all, $duration: 0.3s, $timing: ease) {
  transition: $property $duration $timing;
}

// 5. 可访问性混合宏
@mixin visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

// 6. 工具类混合宏
@mixin generate-utility-classes($property, $values, $prefix) {
  @each $key, $value in $values {
    .#{$prefix}-#{$key} {
      #{$property}: $value;
    }
  }
}

通过遵循这些团队协作规范,可以确保团队成员之间的Sass开发工作高效、一致且可维护。