惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Troy Hunt's Blog
Scott Helme
Scott Helme
T
Threat Research - Cisco Blogs
T
Tenable Blog
L
LINUX DO - 热门话题
V
Visual Studio Blog
I
Intezer
Blog — PlanetScale
Blog — PlanetScale
Cisco Talos Blog
Cisco Talos Blog
A
Arctic Wolf
C
Cyber Attacks, Cyber Crime and Cyber Security
F
Fortinet All Blogs
aimingoo的专栏
aimingoo的专栏
Know Your Adversary
Know Your Adversary
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
N
Netflix TechBlog - Medium
SecWiki News
SecWiki News
I
InfoQ
Microsoft Security Blog
Microsoft Security Blog
Project Zero
Project Zero
W
WeLiveSecurity
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
Recorded Future
Recorded Future
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Vercel News
Vercel News
S
Securelist
Spread Privacy
Spread Privacy
L
LangChain Blog
云风的 BLOG
云风的 BLOG
G
Google Developers Blog
MongoDB | Blog
MongoDB | Blog
Google DeepMind News
Google DeepMind News
Recent Commits to openclaw:main
Recent Commits to openclaw:main
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
CERT Recently Published Vulnerability Notes
罗磊的独立博客
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
The Last Watchdog
The Last Watchdog
Attack and Defense Labs
Attack and Defense Labs
博客园 - 司徒正美
Help Net Security
Help Net Security
L
Lohrmann on Cybersecurity
人人都是产品经理
人人都是产品经理
Forbes - Security
Forbes - Security
Hacker News - Newest:
Hacker News - Newest: "LLM"
PCI Perspectives
PCI Perspectives
博客园 - 【当耐特】
T
Tor Project blog

博客园 - 箫笛

Tkinter - tk 变量 Tkinter - 事件与绑定 Tkinter - 几何管理器 Tkinter - 核心概念 Tkinter - 快速开始 Tkinter - 介绍 Python 编程 - 条件表达式 Python 编程 - 星号下划线参数释义 shell 编程 - shell 脚本的交互方式 Python insall - macOS 系统安装python的几种方式 Miniconda - Python 环境管理工具 Tkinter - Python GUI 开发 Python 编程 - 下划线命名的区别 Python 编程 - 元类编程 Python 编程 - 多重继承与MRO Python 编程 - 描述符协议 Python 编程 - 类型注解 Python 编程 - 生成器表达式 Python 编程 - 集合 Python 编程 - 装饰器 Python 编程 - 闭包 Python 编程 - 列表推导式 Python 编程 - 函数式编程 Python 编程 - lambda 函数 Python 编程 - 文件操作 Python 编程 - 输入与输出 Python 编程 - 面向对象编程 Python 编程 - 元组(tuple) Python 编程 - 字符串(str) Python 编程 - 字典(dict) Python 编程 - 列表(list) Python 编程 - 数据类型和数据结构 Python 编程 - 语句 Python 编程 - 函数 windows - WSL 的安装与使用 shell编程 - dialog 程序使用指南 FE Team - 如何做好前端代码审查 git 提交的撤销和恢复 React15 - redux-saga 如何在saga中实现轮询接口调用? React15 - React CSS Modules BEM命名实践 React15 - React 15 中 componentWillReceiveProps 为什么会多次调用, 同时componentDidUpdate 也会多次调用? React15 - React15类组件多次执行render方法的原因? React15 - React15应用中代码逻辑复用方案 React15 - React状态同步问题解决 React15 - React 15 中 React.pureComponent 的使用场景 React15 - React 15应用在页面渲染时会多次执行类组件的render 函数的原因 React15 - React 15 中能用 componetDidUpdate 代替 componentWillReceiveProps 吗? React15 - React 15 生命周期函数详解 React15 - 如何在React 15中实现自定义的事件订阅与发送(例如组件间通信) React15 - React15应用中的事件订阅和发送机制 React15 - CSS中的BEM规范 React15 - React CSS Modules BEM命名实践 React15 - 写sass 样式文件,嵌套的结构好,还是扁平的结构好? React15 - sass 中 @mixin 和 @extend 的区别是什么? React15 - React15应用Sass使用指南 React15 - React 15 应用如何进行性能优化?
React15 - React 15 应用 如何使用Css moudules 方式进行模块化开发
箫笛 · 2026-03-22 · via 博客园 - 箫笛

在 React 15 项目中,使用 CSS Modules 进行组件的样式模块化开发,是当时解决样式冲突和提升代码可维护性的最佳实践。核心思路是每个组件都拥有一个独立且唯一的样式文件,并通过对象属性的方式在 JavaScript 中引用类名

下面我将从配置、开发规范、以及在 React 15 生命周期中的使用技巧这几个方面,为你详细拆解。

一、确保 CSS Modules 配置正确

在开始开发之前,首先要确保 Webpack 的配置支持 CSS Modules。正如上一步提到的,关键点在于 css-loadermodules 选项。

推荐配置(支持局部样式和全局样式混用):

// webpack.config.js 文件片段
module.exports = {
  module: {
    rules: [
      {
        test: /\.(scss|sass)$/, // 匹配模块化开发的 Sass 文件
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              modules: {
                // localIdentName 定义了编译后的类名格式
                // [path] 文件路径
                // [name] 文件名
                // [local] 原始类名
                // [hash:base64:5] 5位 base64 哈希,确保唯一性
                localIdentName: "[name]__[local]--[hash:base64:5]",
              },
              // 告诉 css-loader 在解析 CSS 时,需要先经过几个 loader 处理
              // 这里设为 1,意味着先经过 sass-loader 处理
              importLoaders: 1,
            },
          },
          "sass-loader", // 将 Sass 编译为 CSS
        ],
      },
      // 注意:如果还有普通的全局 CSS 文件,可以单独配置
      {
        test: /\.global\.css$/, // 约定以 .global.css 结尾的文件作为全局样式
        use: ["style-loader", "css-loader"], // 不使用 modules 选项
      },
    ],
  },
};

配置解读:

  • localIdentName:这是一个很有用的配置。在生产环境你可能希望它尽量短(如 [hash:base64:8]),但在开发环境中,建议设置得像示例中那样详细。当你使用浏览器开发者工具查看元素时,你可以一眼看出这个类名来自哪个组件、原始名称是什么,极大地提升了调试体验
  • importLoaders: 1:这个选项告诉 css-loader,在它处理文件内容之前,需要先经过几个 loader 的处理。因为这里用到了 Sass,所以需要设置为 1,先让 sass-loader 工作。

二、组件的样式模块化开发实践

配置完成后,就可以开始编写模块化的样式了。

1. 文件命名规范

通常建议将样式文件命名为 [组件名].module.scss(或 .module.sass.module.css)。虽然 React 15 并不强制要求文件名包含 .module,但遵循这个社区惯例可以帮助你和团队成员快速区分“模块化样式”和“普通全局样式”。

2. 在组件中导入和使用

假设我们要开发一个 Card 组件:

第一步:创建样式文件 (src/components/Card/Card.module.scss)

// 局部样式:这里定义的类名默认都是局部的
.card {
  border: 1px solid #eee;
  border-radius: 8px;
  padding: 16px;
  background-color: white;
}

.title {
  font-size: 18px;
  font-weight: bold;
  color: #333;
  margin-bottom: 8px;
}

.description {
  font-size: 14px;
  color: #666;
  line-height: 1.5;
}

// 特殊状态样式
.is-expanded {
  .description {
    // 当卡片处于展开状态时,显示更多内容
    max-height: none;
  }
}

// 全局覆盖:如果你真的需要定义一个全局样式(极少情况),可以使用 :global 包裹
:global .clearfix {
  clear: both;
}

第二步:在 React 组件中使用 (src/components/Card/Card.js)

import React from "react";
// 关键点:将样式文件作为一个对象导入
import styles from "./Card.module.scss";

class Card extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      expanded: false,
    };
  }

  // React 15 中常用的事件处理方法
  toggleExpand = () => {
    this.setState((prevState) => ({
      expanded: !prevState.expanded,
    }));
  };

  render() {
    const { title, description } = this.props;
    const { expanded } = this.state;

    // 技巧:动态组合类名
    // styles.card 始终存在
    // 如果 expanded 为 true,则添加 styles['is-expanded']
    const cardClasses = [styles.card, expanded ? styles["is-expanded"] : ""]
      .join(" ")
      .trim();

    return (
      // 使用 styles 对象的属性来引用类名
      <div className={cardClasses}>
        <h3 className={styles.title}>{title}</h3>
        <p className={styles.description}>{description}</p>
        <button onClick={this.toggleExpand}>
          {expanded ? "收起" : "展开"}
        </button>
        {/* 使用全局样式 */}
        <div className="clearfix"></div>
      </div>
    );
  }
}

export default Card;

三、在 React 15 中的特殊注意事项

1. 处理多个类名的组合

在 React 15 中,classnames 这个第三方库非常流行,专门用来处理条件类名。它和 CSS Modules 配合得很好。

安装 classnames:

npm install classnames --save

使用示例:

import classNames from 'classnames';
import styles from './Card.module.scss';

// 在 render 方法中
render() {
  const { expanded } = this.state;
  const { isFeatured } = this.props;

  const cardClasses = classNames(
    styles.card, // 基础样式
    {
      [styles['is-expanded']]: expanded, // 条件样式
      [styles['is-featured']]: isFeatured // 条件样式
    }
  );

  return <div className={cardClasses}>...</div>
}

2. 组件间样式复用(组合而非继承)

在模块化开发中,如果想要复用样式,不建议通过在一个组件中导入另一个组件的样式文件来实现。

推荐做法:将通用的样式抽离成 Sass 的混合宏 (mixin)占位符 (%)

定义通用样式 (src/styles/mixins.scss):

// 定义一个清除浮动的 mixin
@mixin clearfix {
  &::after {
    content: "";
    clear: both;
    display: table;
  }
}

// 定义一个卡片阴影的占位符
%card-shadow {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: box-shadow 0.3s ease;

  &:hover {
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
  }
}

在组件样式中使用 (src/components/Card/Card.module.scss):

@import "../../styles/mixins.scss";

.card {
  @include clearfix; // 引入 mixin
  @extend %card-shadow; // 继承占位符
  // ... 其他样式
}

3. 关于 :export 关键字

你可能会在资料中看到 CSS Modules 支持 :export 语法,用于在 JavaScript 和 CSS 之间共享变量。这在 React 15 项目中也是完全可用的,但需要确保 css-loader 版本在 0.14.0 以上。

// Card.module.scss
$primary-color: #1890ff;

:export {
  primaryColor: $primary-color;
  cardPadding: 16px;
}
// Card.js
import styles, { primaryColor, cardPadding } from "./Card.module.scss";

console.log(primaryColor); // 输出 '#1890ff'
console.log(cardPadding); // 输出 '16px'

这个特性对于保持主题样式变量的一致性非常有帮助。

总结

在 React 15 中通过 CSS Modules 进行模块化开发,核心是建立起一种约定

  1. 约定配置:确保 Webpack 正确配置了 moduleslocalIdentName
  2. 约定导入:统一使用 import styles from './ComponentName.module.scss'
  3. 约定使用:始终通过 styles.className 的方式引用类名,利用 classnames 处理复杂逻辑。
  4. 约定复用:通过 Sass 的 @mixin@extend 实现样式的抽离和复用。

这套方案在 React 15 时代非常成熟,能有效解决大型项目的样式维护问题。