React 样式方案

各有优缺点,选对场景最重要

1. CSS Modules

原理:构建工具把类名编译成哈希字符串。

/* Button.module.css */
.button {
  background: blue;
}
import styles from './Button.module.css';

<button className={styles.button}>点我</button>

编译后:class="button_abc123"

优点

  • 零运行时开销 — 纯 CSS,不影响 JS 包体积
  • 不冲突 — 哈希命名,永远不担心类名重复
  • 老牌稳定 — 兼容性好

缺点

  • 动态样式写起来麻烦(需要配合 classnames 库)

为什么需要 classnames?

CSS Modules 的类名是编译后生成的,但实际项目中经常需要根据条件切换样式:

// ❌ 字符串拼接太繁琐
<button className={styles.button + (isActive ? ' ' + styles.active : '')}>

// ✅ 用 classnames 简化
import cx from 'classnames';

<button className={cx(styles.button, { [styles.active]: isActive })}>

classnames 可以优雅地合并多个类名,支持对象/数组/字符串写法,比字符串拼接干净多了。

2. CSS-in-JS (Styled-Components / Emotion)

原理:在 JS 里写 CSS,运行时生成 style 标签。

import styled from 'styled-components';

const Button = styled.button`
  background: ${props => props.primary ? 'blue' : 'gray'};
`;

<Button primary>点我</Button>

优点

  • 动态性强 — 直接读 props 生成样式
  • 主题化方便 — 配合 ThemeProvider 轻松换肤

缺点

  • 运行时开销 — 每次渲染要解析 CSS、生成哈希、插入 style 标签
  • 包体积大 — 增加了库的大小

3. 原子化 CSS (Tailwind CSS)

原理:用工具类组合 UI。

<button className="flex items-center justify-center px-4 py-2 bg-blue-500 text-white rounded">
  点我
</button>

优点

  • 开发超快 — 不用在 HTML 和 CSS 之间来回切换
  • 体积小 — 构建时 PurgeCSS 只保留用到的类
  • 约束设计 — 强制统一间距、颜色

缺点

  • HTML 类名很长,可读性差(VSCode 插件可以解决)
  • 学习成本(要记一堆类名)

怎么选?

场景推荐方案
大多数项目Tailwind CSS(效率王)
组件库开发CSS-in-JS(方便换肤)或 CSS Modules(无依赖)
性能敏感CSS Modules 或 Tailwind
快速开发Tailwind

总结

  • CSS Modules:稳定、性能好,但动态样式麻烦
  • CSS-in-JS:动态强、主题方便,但有运行时开销
  • Tailwind:开发快、体积小,但类名长

按需选用,没有银弹。