Appearance
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开发工作高效、一致且可维护。