框架集成
框架集成
Sass/SCSS 可以与各种现代前端框架无缝集成,提供更强大的样式管理能力。本文将介绍如何在主流前端框架中配置和使用 Sass,以及一些实用的集成技巧。
React配置示例
在React项目中配置Sass:
Create React App
Create React App 提供了内置的 Sass 支持:
// 使用Create React App
// 安装依赖
// npm install sass
// 直接导入.scss文件
import './styles.scss';
// 在组件中使用
function App() {
return (
<div className="app">
<button className="button button--primary">点击我</button>
</div>
);
}
CSS Modules
在 React 中使用 Sass 和 CSS Modules:
// Button.module.scss
.button {
padding: 10px 15px;
border-radius: 4px;
&.primary {
background-color: #007bff;
color: white;
}
&.secondary {
background-color: #6c757d;
color: white;
}
}
// Button.jsx
import React from 'react';
import styles from './Button.module.scss';
function Button({ children, variant = 'primary' }) {
return (
<button
className={`${styles.button} ${styles[variant]}`}
>
{children}
</button>
);
}
export default Button;
自定义配置 (使用 CRACO)
对于需要自定义 Webpack 配置的项目,可以使用 CRACO:
// 安装依赖
// npm install @craco/craco
// craco.config.js
const path = require('path');
module.exports = {
style: {
sass: {
loaderOptions: {
// 全局导入变量和混入
additionalData: `
@import "src/styles/variables.scss";
@import "src/styles/mixins.scss";
`
}
}
},
webpack: {
alias: {
'@styles': path.resolve(__dirname, 'src/styles')
}
}
};
// package.json
{
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test"
}
}
Next.js 配置
在 Next.js 项目中配置 Sass:
// 安装依赖
// npm install sass
// next.config.js
const path = require('path');
module.exports = {
sassOptions: {
includePaths: [path.join(__dirname, 'styles')],
prependData: `@import "variables.scss";`
}
}
Vue配置示例
在Vue项目中配置Sass:
Vue CLI
Vue CLI 提供了内置的 Sass 支持:
// vue.config.js
module.exports = {
css: {
loaderOptions: {
sass: {
additionalData: `@import "@/styles/variables.scss";`
}
}
}
}
<!-- 组件中使用 -->
<template>
<div class="container">
<button class="button">点击我</button>
</div>
</template>
<style lang="scss">
.container {
.button {
background-color: $primary-color;
color: white;
}
}
</style>
Nuxt.js 配置
在 Nuxt.js 项目中配置 Sass:
// nuxt.config.js
export default {
css: [
'@/assets/scss/main.scss'
],
build: {
loaders: {
scss: {
additionalData: '@import "@/assets/scss/variables.scss";'
}
}
}
}
Vue 3 + Vite
在 Vite 驱动的 Vue 3 项目中配置 Sass:
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
export default defineConfig({
plugins: [vue()],
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`,
// 配置路径别名
importer: [
(url) => {
if (url.startsWith('~')) {
return { file: path.resolve(__dirname, 'node_modules', url.slice(1)) }
}
return null
}
]
}
}
},
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@styles': path.resolve(__dirname, 'src/styles')
}
}
})
Angular配置示例
Angular 默认支持 Sass:
基本配置
# 创建新项目时选择 SCSS
ng new my-app --style=scss
# 或修改现有项目
ng config schematics.@schematics/angular:component.style scss
全局样式配置
// angular.json
{
"projects": {
"my-app": {
"architect": {
"build": {
"options": {
"styles": [
"src/styles.scss"
],
"stylePreprocessorOptions": {
"includePaths": [
"src/styles"
]
}
}
}
}
}
}
}
组件中使用
// app.component.ts
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'my-app';
}
// app.component.scss
@import 'variables';
:host {
display: block;
padding: $spacing-md;
.container {
background-color: $background-color;
h1 {
color: $primary-color;
}
}
}
Svelte配置示例
Svelte 也可以轻松集成 Sass:
基本配置
// 安装依赖
// npm install svelte-preprocess sass
// svelte.config.js
const sveltePreprocess = require('svelte-preprocess');
module.exports = {
preprocess: sveltePreprocess({
scss: {
prependData: `@import 'src/styles/variables.scss';`
}
})
};
Svelte 组件中使用
<!-- Button.svelte -->
<script>
export let variant = 'primary';
</script>
<button class={`button button--${variant}`}>
<slot></slot>
</button>
<style lang="scss">
.button {
padding: 10px 15px;
border-radius: 4px;
&--primary {
background-color: $primary-color;
color: white;
}
&--secondary {
background-color: $secondary-color;
color: white;
}
}
</style>
UI 框架集成
Bootstrap 集成
将 Bootstrap 与 Sass 集成可以自定义 Bootstrap 变量:
// custom-bootstrap.scss
// 自定义变量
$primary: #3f51b5;
$secondary: #ff4081;
$success: #4caf50;
$info: #2196f3;
$warning: #ff9800;
$danger: #f44336;
// 导入 Bootstrap
@import "~bootstrap/scss/bootstrap";
// 在入口文件中导入
import './custom-bootstrap.scss';
Tailwind CSS 集成
将 Tailwind CSS 与 Sass 集成:
// 安装依赖
// npm install tailwindcss postcss autoprefixer
// tailwind.config.js
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx,vue,svelte}",
],
theme: {
extend: {
colors: {
primary: '#3f51b5',
secondary: '#ff4081'
}
}
},
plugins: []
}
// main.scss
@tailwind base;
@tailwind components;
@tailwind utilities;
// 自定义 Sass 样式
@layer components {
.btn {
@apply py-2 px-4 rounded;
&-primary {
@apply bg-primary text-white;
}
&-secondary {
@apply bg-secondary text-white;
}
}
}
Material UI 集成
将 Material UI 与 Sass 集成:
// theme.js
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
palette: {
primary: {
main: '#3f51b5',
},
secondary: {
main: '#ff4081',
},
},
});
export default theme;
// styles.scss
@use '@mui/material' as mui;
// 自定义 Material UI 样式
.MuiButton-root {
text-transform: none;
}
// 使用 Material UI 变量
.custom-element {
color: mui.$primary-main;
background-color: mui.$secondary-light;
}
移动应用框架集成
React Native 集成
在 React Native 中使用类似 Sass 的功能(通过 React Native Sass Transformer):
// 安装依赖
// npm install --save-dev react-native-sass-transformer sass
// metro.config.js
const { getDefaultConfig } = require('metro-config');
module.exports = (async () => {
const {
resolver: { sourceExts }
} = await getDefaultConfig();
return {
transformer: {
babelTransformerPath: require.resolve('react-native-sass-transformer')
},
resolver: {
sourceExts: [...sourceExts, 'scss', 'sass']
}
};
})();
// styles.scss
$primary-color: #3f51b5;
$text-color: #333;
%button-base {
padding: 10px 15px;
border-radius: 4px;
}
.button {
@extend %button-base;
background-color: $primary-color;
color: white;
}
// Button.js
import React from 'react';
import { TouchableOpacity, Text } from 'react-native';
import styles from './styles.scss';
const Button = ({ title }) => (
<TouchableOpacity style={styles.button}>
<Text>{title}</Text>
</TouchableOpacity>
);
export default Button;
Ionic 框架集成
Ionic 框架原生支持 Sass:
// variables.scss
$primary: #3880ff;
$secondary: #3dc2ff;
$danger: #eb445a;
// 自定义 Ionic 变量
$colors: (
primary: $primary,
secondary: $secondary,
danger: $danger
);
// 导入 Ionic
@import "~@ionic/angular/css/ionic.bundle.css";
// home.page.scss
.container {
ion-button {
--background: var(--ion-color-primary);
&.secondary {
--background: var(--ion-color-secondary);
}
}
}
实用集成技巧
主题切换
使用 Sass 变量实现主题切换:
// _themes.scss
$themes: (
light: (
background-color: #ffffff,
text-color: #333333,
primary-color: #3f51b5,
secondary-color: #ff4081
),
dark: (
background-color: #121212,
text-color: #ffffff,
primary-color: #7986cb,
secondary-color: #ff80ab
)
);
@mixin themed() {
@each $theme, $map in $themes {
.theme-#{$theme} & {
$theme-map: () !global;
@each $key, $value in $map {
$theme-map: map-merge($theme-map, ($key: $value)) !global;
}
@content;
$theme-map: null !global;
}
}
}
@function t($key) {
@return map-get($theme-map, $key);
}
// component.scss
@import 'themes';
.card {
@include themed() {
background-color: t(background-color);
color: t(text-color);
border: 1px solid rgba(t(text-color), 0.1);
.card-title {
color: t(primary-color);
}
.card-button {
background-color: t(secondary-color);
color: t(background-color);
}
}
}
// 在 JavaScript 中切换主题
document.body.classList.remove('theme-light', 'theme-dark');
document.body.classList.add('theme-dark'); // 或 'theme-light'
响应式设计
使用 Sass 混入实现响应式设计:
// _breakpoints.scss
$breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
xxl: 1400px
);
@mixin media-up($breakpoint) {
$min: map-get($breakpoints, $breakpoint);
@if $min {
@media (min-width: $min) {
@content;
}
} @else {
@content;
}
}
@mixin media-down($breakpoint) {
$max: map-get($breakpoints, $breakpoint);
@if $max {
@media (max-width: $max - 1) {
@content;
}
} @else {
@content;
}
}
@mixin media-between($lower, $upper) {
$min: map-get($breakpoints, $lower);
$max: map-get($breakpoints, $upper);
@if $min and $max {
@media (min-width: $min) and (max-width: $max - 1) {
@content;
}
}
}
// 使用响应式混入
.container {
padding: 15px;
@include media-up(md) {
padding: 30px;
}
.sidebar {
display: none;
@include media-up(lg) {
display: block;
width: 250px;
}
}
.content {
width: 100%;
@include media-up(lg) {
width: calc(100% - 270px);
margin-left: 20px;
}
}
}
CSS-in-JS 集成
将 Sass 理念与 CSS-in-JS 库结合使用:
// 使用 styled-components
import styled from 'styled-components';
import { darken, lighten } from 'polished';
// 定义变量(类似 Sass 变量)
const theme = {
colors: {
primary: '#3f51b5',
secondary: '#ff4081',
text: '#333333',
background: '#ffffff'
},
spacing: {
sm: '8px',
md: '16px',
lg: '24px'
},
breakpoints: {
sm: '576px',
md: '768px',
lg: '992px'
}
};
// 创建混入(类似 Sass 混入)
const flexCenter = `
display: flex;
justify-content: center;
align-items: center;
`;
const mediaUp = (breakpoint) => `@media (min-width: ${theme.breakpoints[breakpoint]})`;
// 创建组件
const Button = styled.button`
padding: ${theme.spacing.sm} ${theme.spacing.md};
border-radius: 4px;
border: none;
cursor: pointer;
${flexCenter}
${props => props.primary && `
background-color: ${theme.colors.primary};
color: white;
&:hover {
background-color: ${darken(0.1, theme.colors.primary)};
}
`}
${props => props.secondary && `
background-color: ${theme.colors.secondary};
color: white;
&:hover {
background-color: ${darken(0.1, theme.colors.secondary)};
}
`}
${mediaUp('md')} {
padding: ${theme.spacing.md} ${theme.spacing.lg};
}
`;
// 使用组件
function App() {
return (
<div>
<Button primary>主要按钮</Button>
<Button secondary>次要按钮</Button>
</div>
);
}
CSS 模块化集成
在不同框架中使用 CSS Modules 与 Sass:
// Button.module.scss
@import 'variables';
.button {
padding: $spacing-sm $spacing-md;
border-radius: $border-radius;
border: none;
cursor: pointer;
&.primary {
background-color: $primary-color;
color: white;
&:hover {
background-color: darken($primary-color, 10%);
}
}
&.secondary {
background-color: $secondary-color;
color: white;
&:hover {
background-color: darken($secondary-color, 10%);
}
}
@media (min-width: $breakpoint-md) {
padding: $spacing-md $spacing-lg;
}
}
React 中使用
// React 中使用 CSS Modules
import React from 'react';
import styles from './Button.module.scss';
import classNames from 'classnames';
function Button({ children, variant = 'primary', className, ...props }) {
return (
<button
className={classNames(
styles.button,
{
[styles.primary]: variant === 'primary',
[styles.secondary]: variant === 'secondary'
},
className
)}
{...props}
>
{children}
</button>
);
}
export default Button;
Vue 中使用
<!-- Vue 中使用 CSS Modules -->
<template>
<button :class="[$style.button, $style[variant]]">
<slot></slot>
</button>
</template>
<script>
export default {
props: {
variant: {
type: String,
default: 'primary',
validator: value => ['primary', 'secondary'].includes(value)
}
}
}
</script>
<style module lang="scss">
@import '@/styles/variables.scss';
.button {
padding: $spacing-sm $spacing-md;
border-radius: $border-radius;
border: none;
cursor: pointer;
&.primary {
background-color: $primary-color;
color: white;
&:hover {
background-color: darken($primary-color, 10%);
}
}
&.secondary {
background-color: $secondary-color;
color: white;
&:hover {
background-color: darken($secondary-color, 10%);
}
}
}
</style>
构建工具优化
生产环境优化
在生产环境中优化 Sass 编译:
// webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
mode: 'production',
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: {
localIdentName: '[hash:base64:8]'
}
}
},
'postcss-loader',
'sass-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css'
})
],
optimization: {
minimizer: [
'...',
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
'default',
{
discardComments: { removeAll: true },
normalizeWhitespace: false
}
]
}
})
],
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true
}
}
}
}
};
开发环境优化
在开发环境中优化 Sass 编译速度:
// webpack.config.js (开发环境)
module.exports = {
mode: 'development',
devtool: 'eval-source-map',
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: {
localIdentName: '[name]__[local]--[hash:base64:5]'
},
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
sassOptions: {
outputStyle: 'expanded'
}
}
}
]
}
]
},
cache: {
type: 'filesystem'
}
};
实际项目案例
企业级应用架构
一个企业级应用的 Sass 架构示例:
src/
├── styles/
│ ├── abstracts/
│ │ ├── _variables.scss # 全局变量
│ │ ├── _functions.scss # 自定义函数
│ │ ├── _mixins.scss # 混入集合
│ │ └── _index.scss # 导出所有抽象
│ ├── base/
│ │ ├── _reset.scss # 样式重置
│ │ ├── _typography.scss # 排版样式
│ │ └── _index.scss # 基础样式导出
│ ├── components/
│ │ ├── _buttons.scss # 按钮样式
│ │ ├── _cards.scss # 卡片样式
│ │ └── _index.scss # 组件样式导出
│ ├── layouts/
│ │ ├── _grid.scss # 网格系统
│ │ ├── _header.scss # 头部布局
│ │ └── _index.scss # 布局样式导出
│ ├── themes/
│ │ ├── _light.scss # 亮色主题
│ │ ├── _dark.scss # 暗色主题
│ │ └── _index.scss # 主题样式导出
│ └── main.scss # 主样式文件
├── components/
│ ├── Button/
│ │ ├── Button.jsx # 按钮组件
│ │ ├── Button.module.scss # 按钮样式
│ │ └── index.js # 导出
│ └── Card/
│ ├── Card.jsx # 卡片组件
│ ├── Card.module.scss # 卡片样式
│ └── index.js # 导出
└── pages/
├── Home/
│ ├── Home.jsx # 首页组件
│ ├── Home.module.scss # 首页样式
│ └── index.js # 导出
└── About/
├── About.jsx # 关于页组件
├── About.module.scss # 关于页样式
└── index.js # 导出
电子商务网站示例
电子商务网站的 Sass 集成示例:
// 使用 Next.js + Sass + CSS Modules
// pages/product/[id].js
import { useState } from 'react';
import Image from 'next/image';
import styles from './Product.module.scss';
export default function Product({ product }) {
const [selectedSize, setSelectedSize] = useState(null);
const [quantity, setQuantity] = useState(1);
return (
<div className={styles.productPage}>
<div className={styles.productGallery}>
<Image
src={product.images[0]}
alt={product.name}
width={500}
height={500}
className={styles.mainImage}
/>
<div className={styles.thumbnails}>
{product.images.map((image, index) => (
<Image
key={index}
src={image}
alt={`${product.name} - ${index}`}
width={80}
height={80}
className={styles.thumbnail}
/>
))}
</div>
</div>
<div className={styles.productInfo}>
<h1 className={styles.productName}>{product.name}</h1>
<div className={styles.productPrice}>${product.price.toFixed(2)}</div>
<div className={styles.productDescription}>
{product.description}
</div>
<div className={styles.productOptions}>
<div className={styles.sizeSelector}>
<h3>尺寸</h3>
<div className={styles.sizeOptions}>
{product.sizes.map(size => (
<button
key={size}
className={`
${styles.sizeOption}
${selectedSize === size ? styles.selected : ''}
`}
onClick={() => setSelectedSize(size)}
>
{size}
</button>
))}
</div>
</div>
<div className={styles.quantitySelector}>
<h3>数量</h3>
<div className={styles.quantityControls}>
<button
className={styles.quantityButton}
onClick={() => setQuantity(Math.max(1, quantity - 1))}
>
-
</button>
<span className={styles.quantityValue}>{quantity}</span>
<button
className={styles.quantityButton}
onClick={() => setQuantity(quantity + 1)}
>
+
</button>
</div>
</div>
</div>
<button className={styles.addToCartButton}>
添加到购物车
</button>
</div>
</div>
);
}
export async function getServerSideProps({ params }) {
// 从 API 获取产品数据
const product = await fetch(`https://api.example.com/products/${params.id}`)
.then(res => res.json());
return {
props: {
product
}
};
}
// Product.module.scss
@import 'styles/abstracts/index';
.productPage {
display: flex;
flex-direction: column;
padding: $spacing-lg;
@include media-up(md) {
flex-direction: row;
gap: $spacing-xl;
}
}
.productGallery {
flex: 1;
.mainImage {
width: 100%;
height: auto;
border-radius: $border-radius;
margin-bottom: $spacing-md;
}
.thumbnails {
display: flex;
gap: $spacing-sm;
overflow-x: auto;
.thumbnail {
width: 80px;
height: 80px;
border-radius: $border-radius-sm;
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
}
}
.productInfo {
flex: 1;
.productName {
font-size: 1.8rem;
font-weight: $font-weight-bold;
margin-bottom: $spacing-sm;
}
.productPrice {
font-size: 1.5rem;
color: $color-primary;
font-weight: $font-weight-bold;
margin-bottom: $spacing-md;
}
.productDescription {
margin-bottom: $spacing-lg;
line-height: 1.6;
}
.productOptions {
margin-bottom: $spacing-lg;
h3 {
margin-bottom: $spacing-sm;
}
.sizeOptions {
display: flex;
gap: $spacing-sm;
margin-bottom: $spacing-md;
.sizeOption {
padding: $spacing-sm $spacing-md;
border: 1px solid $color-border;
border-radius: $border-radius-sm;
background: none;
cursor: pointer;
&.selected {
border-color: $color-primary;
color: $color-primary;
}
&:hover:not(.selected) {
background-color: $color-background-light;
}
}
}
.quantityControls {
display: flex;
align-items: center;
.quantityButton {
width: 36px;
height: 36px;
border: 1px solid $color-border;
background: none;
font-size: 1.2rem;
cursor: pointer;
&:hover {
background-color: $color-background-light;
}
}
.quantityValue {
padding: 0 $spacing-md;
font-size: 1rem;
}
}
}
.addToCartButton {
width: 100%;
padding: $spacing-md;
background-color: $color-primary;
color: white;
border: none;
border-radius: $border-radius;
font-size: 1rem;
font-weight: $font-weight-bold;
cursor: pointer;
&:hover {
background-color: darken($color-primary, 10%);
}
}
}
常见问题与解决方案
全局变量访问问题
问题:在不同组件中无法访问全局 Sass 变量
解决方案:
- 使用全局导入:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
additionalData: `@import "src/styles/variables.scss";`
}
}
]
}
]
}
};
- 创建变量索引文件:
// _variables.scss
$primary-color: #3f51b5;
$secondary-color: #ff4081;
// 在每个需要变量的文件中导入
@import 'path/to/variables';
样式冲突问题
问题:组件样式相互冲突
解决方案:
- 使用 CSS Modules:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]__[local]--[hash:base64:5]'
}
}
},
'sass-loader'
]
}
]
}
};
- 使用 BEM 命名约定:
.component {
&__element {
// 元素样式
&--modifier {
// 修饰符样式
}
}
}
编译性能问题
问题:Sass 编译速度慢
解决方案:
- 使用 Dart Sass 代替 Node Sass:
npm uninstall node-sass
npm install sass
- 减少 @import 使用,改用 @use:
// 旧方式
@import 'variables';
@import 'mixins';
// 新方式
@use 'variables' as vars;
@use 'mixins' as mix;
.element {
color: vars.$primary-color;
@include mix.center;
}
- 启用缓存:
// webpack.config.js
module.exports = {
cache: {
type: 'filesystem'
}
};
浏览器兼容性问题
问题:生成的 CSS 在某些浏览器中不兼容
解决方案:
- 使用 PostCSS 和 Autoprefixer:
// postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
]
};
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader'
]
}
]
}
};
- 设置目标浏览器:
// package.json
{
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
最佳实践总结
组织结构
- 遵循模块化原则:将样式分解为小型、可重用的模块
- 采用 7-1 模式:将样式文件组织为 7 个文件夹和 1 个主文件
- 组件化设计:每个组件拥有自己的样式文件
性能优化
- 减少嵌套层级:嵌套不超过 3 层
- 避免过度使用 @extend:优先使用 @mixin
- 使用 CSS Modules 或 BEM:避免全局样式污染
- 启用缓存和压缩:加速开发和生产环境
可维护性
- 使用变量存储常用值:颜色、字体、间距等
- 创建混入封装常用模式:响应式、动画等
- 编写清晰的注释:说明复杂逻辑和用途
- 遵循一致的命名约定:BEM、命名空间等
跨框架兼容
- 使用框架无关的 Sass 结构:抽象层与框架分离
- 创建可移植的混入和函数:不依赖特定框架
- 使用 CSS Modules:提供框架间的样式隔离
总结
Sass/SCSS 与现代前端框架的集成为开发者提供了强大的样式管理能力。通过本文,我们了解了:
- 如何在 React、Vue、Angular 和 Svelte 等主流框架中配置和使用 Sass
- 如何将 Sass 与 Bootstrap、Tailwind CSS 和 Material UI 等 UI 框架集成
- 如何在移动应用框架中使用 Sass
- 实用的集成技巧,如主题切换和响应式设计
- 常见问题的解决方案和最佳实践
无论你使用哪种前端框架,合理配置和使用 Sass 都能显著提高开发效率、代码可维护性和样式系统的一致性。