如何在反应应用程序中使用CSS模块应用全局样式?

hid*_*ace 42 css reactjs css-modules react-css-modules

我目前正在使用带有React的CSS模块进行造型.所以我的每个组件都导入了它的组件特定的css文件,如下所示:

import React from 'react';
import styles from './App.css';

const example = () => (
  <div className={styles.content}>
    Hello World!
  </div>
);

export default example;
Run Code Online (Sandbox Code Playgroud)

这样在设计单个组件时工作正常,但是如何应用非特定于组件的全局样式(html,正文,标题标记,div等)?

fel*_*omi 67

由于您使用的是ES6导入语法,因此可以使用相同的语法导入样式表

import './App.css'
Run Code Online (Sandbox Code Playgroud)

此外,您可以将您的类包装:global为切换到全局范围(这意味着CSS模块不会对其进行模块化,例如:在其旁边添加随机ID)

:global(.myclass) {
  background-color: red;
}
Run Code Online (Sandbox Code Playgroud)

  • 对我来说,来自像`import './App.css'` 这样导入的文件中的类名根本没有任何影响。它仅适用于您的第二段代码。这是我第一次遇到这个“css 模块”的东西,我已经讨厌它破坏了几千年来有效的东西。 (2认同)
  • @MikhailBatcer 同样的事情也发生在我身上。事实上,我必须使用命名导入,然后应用类。`从 './App.css' 导入类,然后应用 `classes.Myclass` (2认同)

hid*_*ace 7

这可以通过简单地添加:

require('./App.css');
Run Code Online (Sandbox Code Playgroud)

(感谢@elmeister正确回答了这个问题.)

  • 或者为了避免将es模块与commonjs混合,只需`import'./ App.css'` (6认同)

小智 7

我也遇到过同样的问题,找到了以下方法来解决该问题,您可以选择最适合您的方法

  1. 在 webpack 配置中定义两组规则用于解析 css/less 文件。
    • 第一条规则应该是包含所有全局样式,假设它保存在 /styles/ 或类似目录中。
    • 第二条规则是处理所有本地范围的 css 样式,理想情况下这些样式应该位于其组件旁边。
    • 您可以在定义规则时使用包含和排除选项来执行此操作
    • 或者通过强制执行命名约定和相应的编写规则,例如所有 css 模块都将是[name].module.css并且您的测试将检查/.module.(less|css)$/并解析它。

下面给出了一个示例:

      // exclude all global styles for css modules
      {
        test: /\.(less|css)$/,
        exclude: path.resolve(__dirname, './src/styles'),
        use: [
          {
            loader: CssExtractPlugin.loader,
            options: { hot: is_dev, reloadAll: is_dev }
          },
          {
            loader: "css-loader",
            options: { 
                modules: { 
                    localIdentName: '[local]___[hash:base64:5]'
                }
            }
          },
          "postcss-loader",
          "less-loader"
        ]
      },
      // process global styles without css modules
     {
        test: /\.(less|css)$/,
        include: path.resolve(__dirname, './src/styles'),
        use: [
          {
            loader: CssExtractPlugin.loader,
            options: { hot: is_dev, reloadAll: is_dev }
          },
          "css-loader",
          "postcss-loader",
          "less-loader"
        ]
      }
Run Code Online (Sandbox Code Playgroud)
  1. 在编写 css/less 时使用:local 和 :global。如果启用了 css 模块,它将默认为本地模式,您可以在选项中指定模式,如下所示:
          {
            loader: "css-loader",
            options: { 
                modules: { 
                    localIdentName: '[local]___[hash:base64:5]', 
                    mode: 'global',
                }
            }
          },
Run Code Online (Sandbox Code Playgroud)

如果您将模式定义为全局,那么您包含的所有 css 类都不会被散列名称替换,而是只有您指定为 :local 的类才会被赋予唯一名称。例如:

/* this will remain as is */
.header {
   color: blue;
}

:local {
  /* this will become something like item_xSH2sa */
  .item {
   color: yellow;
  }
}

Run Code Online (Sandbox Code Playgroud)
  1. 定义一个函数来检查您的文件以确定它是 css 模块还是全局的,使用getLocalIdent选项完成。这是我当前在设置中使用的方法。这还要求您的文件具有一些命名约定,对于 css 模块为[name].module.less,对于常规文件为 [name].less。请参阅下面的示例:
// regex to test for modules, loaderUtils is part of webpack dependencies
const cssModuleRegex = new RegExp(/\.module\.(less|css)$/);
const loaderUtils = require("loader-utils");

// inside webpack rules
      {
        test: /\.(less|css)$/,
        use: [
          {
            loader: CssExtractPlugin.loader,
            options: { hot: is_dev, reloadAll: is_dev }
          },
          {
            loader: "css-loader",
            options: { 
                modules: { 
                    localIdentName: '[local]___[hash:base64:5]', 
                    getLocalIdent: getLocalIdent
                }
            }
          },
          "postcss-loader",
          "less-loader"
        ]
      }

// this is a copy of the default function, modified slightly to achieve our goal
function getLocalIdent(loaderContext, localIdentName, localName, options) {

    // return local name if it's a global css file
    if (!cssModuleRegex.test(loaderContext.resourcePath)) {
        return localName;
    }

    if (!options.context) {
      // eslint-disable-next-line no-param-reassign
      options.context = loaderContext.rootContext;
    }

    const request = path
      .relative(options.context, loaderContext.resourcePath)
      .replace(/\\/g, '/');

    // eslint-disable-next-line no-param-reassign
    options.content = `${options.hashPrefix + request}+${localName}`;

    // eslint-disable-next-line no-param-reassign
    localIdentName = localIdentName.replace(/\[local\]/gi, localName);

    const hash = loaderUtils.interpolateName(
      loaderContext,
      localIdentName,
      options
    );

    return hash
      .replace(new RegExp('[^a-zA-Z0-9\\-_\u00A0-\uFFFF]', 'g'), '-')
      .replace(/^((-?[0-9])|--)/, '_$1');
  }

Run Code Online (Sandbox Code Playgroud)


Man*_*olo 6

我发现全局导入样式但仅针对特定路线的唯一方法是添加:

<style dangerouslySetInnerHTML={{__html: `
  body { max-width: 100% }
`}} />
Run Code Online (Sandbox Code Playgroud)

在方法的返回内部render

否则,style标签将被添加到<head>,并且样式将应用于所有后续路由。

来自https://medium.learnreact.com/the-style-tag-and-react-24d6dd3ca974

也许可以将样式作为字符串从文件导入,以使代码更有条理。