react 中 CSS Modules 的简单使用(解决组件样式覆盖问题)

项目搭建以及配置

新建一个项目

npx create-react-app learn-css-modules-react
cd learn-css-modules-react
// 显示 webpack 的配置
yarn eject

看到 config/webpack.config.js,默认情况下,React 脚手架搭建出来的项目,只有 .module.css 支持模块化,如果是自己搭建的话,可以支持 .css 文件的后缀等

// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
  test: cssModuleRegex,
  use: getStyleLoaders({
    importLoaders: 1,
    sourceMap: isEnvProduction
      ? shouldUseSourceMap
      : isEnvDevelopment,
    modules: {
      getLocalIdent: getCSSModuleLocalIdent,
    },
  }),
}

其中 getStyleLoaders 函数,可以看到 css-loader 的配置

const getStyleLoaders = (cssOptions, preProcessor) => {
  const loaders = [
    // ...
    {
      loader: require.resolve('css-loader'),
      options: cssOptions,
    },
    // ...
  ];
  // ...
  return loaders;
};

我们就基于这个环境当做示例进行演示

局部作用域

之前的样式

 

 

首先,我们将 App.css 修改成 App.module.css,然后导入 css,并设置(这里有个小知识点,实际上 CSS Modules 推荐的命名是驼峰式,主要是这样的话,使用对象 style.className 就可以访问。如果是如下,就需要 styles['***-***'])
import styles from './App.module.css';

// ...
<header className={styles['App-header']}></header>

就会根据特定的规则生成相应的类名

 

 

这个命名规则是可以通过 CSS-loader 进行配置,类似如下的配置:
module: {
  loaders: [
    // ...
    {
      test: /\.css$/,
      loader: "style-loader!css-loader?modules&localIdentName=[path][name]---[local]---[hash:base64:5]"
    },
  ]
}

全局作用域

默认情况下,我们发现,在 css modules 中定义的类名必须得通过类似设置变量的方式给 HTML 设置(如上示例所示)

那么我能像其他的 CSS 文件一样直接使用类名(也就是普通的设置方法),而不是编译后的哈希字符串么?

使用 :global 的语法,就可以声明一个全局的规则

:global(.App-link) {
  color: #61dafb;
}

这样就可以在 HTML 中直接跟使用普通的 CSS 一样了

但这里感觉就是 CSS Modules 给开发者留的一个后门,我们这样的 CSS,还是直接放在普通 .css 文件中比较好,我理解这就是 React 为什么对待 .css 和 .module.css 不同后缀进行不同的处理的原因

Class 的组合

在 CSS Modules 中,一个选择器可以继承另一个选择器的规则,这称为 "组合"("composition"

比如,我们定义一个 font-red,然后在 .App-header 中使用 composes: font-red; 继承

.font-red {
  color: red;
}

.App-header {
  composes: font-red;
  /* ... */
}

 

输入其他的模块

不仅仅可以同一个文件中的,还可以继承其他文件中的 CSS 规则

定义一个 another.module.css

.font-blue {
  color: blue;
}

在 App.module.css 中

.App-header {
  /* ... */
  composes: font-blue from './another.module.css';
  /* ... */
}

 

使用变量

我们还可以使用变量,定义一个 colors.module.css

@value blue: #0c77f8;

在 App.module.css 中

@value colors: "./colors.module.css";
@value blue from colors;

.App-header {
  /* ... */
  color: blue;
}

posted @ 2022-05-08 17:19  ~逍遥★星辰~  阅读(1194)  评论(0编辑  收藏  举报