CSS 模块、反应和覆盖 CSS 类

CSS Modules, React and Overriding CSS Classes

我正在使用 React 组件库 (React Toolbox),它使用 CSS 模块和 Webpack 在其 Tab 组件中输出此 class:label___1nGy active___1Jur tab___Le7N tab 是我传下来的 className 道具。 labelactive classes 来自图书馆。我想在 active 上应用一组不同的样式,例如 .tab.active,其中 tab 指的是我创建的样式,active 匹配库中生成的选择器创建但无法弄清楚如何使用 css-modules 执行此操作。我需要覆盖这个动态选择器:.label___1nGy.active___1Jur.

[]]2 []3

CSS 模块不允许您安全地覆盖活动类名(主要是设计使然)。实际上,它应该通过 API 公开,例如'activeClassName'.

如果维护者不同意或者您需要快速完成,那么您可以很容易地添加自己的活动类名,因为您的实施组件正在管理索引状态:

import {Tab, Tabs} from 'react-toolbox';
import styles from './MyTabs.css';


class MyTabs extends React.Component {
  state = {
    index: 1
  };

  handleTabChange(index) {
    this.setState({ index });
  }

  render() {
    const { index } = this.state;
    return (
      <Tabs index={index} onChange={this.handleTabChange}>
        <Tab label="Tab0" className={index === 0 ? styles.active : null}>
            Tab 0 content
        </Tab>
        <Tab label="Tab1" className={index === 1 ? styles.active : null}>
            Tab 1 content
        </Tab>
      </Tabs>
    );
  }
}

免责声明:代码未经测试。

我也遇到过类似的情况,我是这样解决的:

import classNames from 'classnames';

...

const activeClassName = {};
activeClassName[`${styles.active}`] = this.props.isActive;
const elementClassNames = classNames(styles.element, activeClassName);

return <div className={elementClassNames} />

我正在使用 classnames 包根据 isActive 道具动态添加活动 class。您可以提供任何布尔值,而不是 isActive 道具。

更简洁的方法可能是:

const elementClassNames = classNames(styles.element, {[styles.active]: this.props.isActive});

旧 post 但仍然相关,因此添加一个答案以帮助那些有类似问题的人

虽然在 CSS 模块中本身不可能,但 react-toolbox 库的作者实际上很好地解决了这个特殊问题

阅读他们的 github 文档,这些文档在 https://github.com/react-toolbox/react-toolbox#customizing-components

上更深入地介绍了该主题

他们网站上的组件演示页面上也给出了特定组件的可主题化 类 列表

在您的情况下,除了为选项卡传递 className 之外,您还可以使用 类 创建一个主题,该主题覆盖默认主题的所需部分并将其作为 theme 道具传递。例如一些类似...

的行

MyComponentWithTabs.css

.tab {
  color: white;
}

MyTabTheme.css

.active {
  color: hotpink;
}

MyComponentWithTabs.js

import styles from './MyComponentWithTabs.css'
import tabTheme from './MyTabTheme.css'

// blah blah...

return <Tab key={index} className={styles.tab} theme={tabTheme} />

在表面之下,这使用了一个装饰器,他们已经抽象到单独的库中 react-css-themr,我建议您也阅读一下,因为它更深入地解释了默认值是如何与您的覆盖组合的,包括不同的合并他们使用的策略

分组样式加载器

您可以使用 group-style-lader 来覆盖组件的样式。这个加载器为您提供了一种简单直观的方法来覆盖组件的样式。

配置加载程序

  1. 安装加载程序

    npm install --save-dev group-style-loader
    
  2. 在你的 webpack 设置中配置加载器

    module.exports = {
      module: {
        rules: [
          {
            test: /\.css$/i,
            use: [
              'group-style-loader', 
              'style-loader', 
              {
                loader: "css-loader",
                options: {
                  modules: true
                }
              }
            ]
          }
        ]
      }
    };
    

You only need to put it, before the style-loader or the mini-css-extract-plugin loader.

覆盖组件的样式

The next example show as you can to override the style of the Card component from the App component.

您可以按照习惯定义组件的样式。

card.css

.container {
  width: 300px;
  height: 400px;
  border-radius: 8px;
}

.title {
  font-weight: bold;
  font-size: 24px;
}

.summary {
  margin-top: 24px;
  font-size: 20px;
}

独特的区别在于,在Card组件中,您将使用mergeStyle函数将自定义样式与组件的默认样式合并。

card.jsx

import React from 'react';
import { mergeStyle } from './card.css';

export function Card({ customStyle }) {

  const style = mergeStyle(customStyle);

  return (
    <div className={style.container}>
      <div className={style.title}>Title</div>
      <div className={style.summary}>
        Lorem ipsum dolor sit amet, consectetur            
        adipiscing elit, sed do eiusmod tempor.
      </div>
    </div>
  )
}

然后,在App组件中,要覆盖Card组件的样式,您需要定义Card的自定义样式使用分隔符 _ 的组件。所有使用此分隔符的 类 将在样式对象的 card 属性 中分组。

app.jsx

.title {
  font-size: 32px;
  font-weight: bold;                
  margin: 44px;
}

.list {
  display: flex;
}

.card_title {
  color: blue;
}

.card_summary {
  color: green;
}

最后只需要将Card组件的自定义样式通过它的customStyle属性即可。

app.jsx

import React from 'react';
import { Card } from './card';
import { style } from './app.css';

export function App() {
  return (
    <div>
      <h1 className={style.title}>Group style</h1>         
      <div className={style.list}>
        <Card/>
        <Card customStyle={style.card}/>
      </div>
    </div>
  );
}

在前面的示例中,您有两个 Cards 组件,第一个使用其默认样式,第二个使用我们定义的自定义样式。

您可以在 repository.

中查看如何使用 group-style-loader 的完整说明

fileName.css

中的技巧

在声明类名

后添加className-active
.className{
  background: white;
}

.className-active{
  background: black;
}

<div className={'className className-active'} />
<div className={'className-active className'} />

divs 永远是黑色

使用 :global(.classname) 你可以覆盖外部类名。

甚至可以覆盖第 3 方库 css。

:global(.active) {
  color: hotpink;
}