CSS 模块、React 和覆盖 CSS 类

Posted

技术标签:

【中文标题】CSS 模块、React 和覆盖 CSS 类【英文标题】:CSS Modules, React and Overriding CSS Classes 【发布时间】:2016-05-14 14:10:20 【问题描述】:

我正在使用 React 组件库(React Toolbox),它使用 CSS 模块和 Webpack 在其 Tab 组件中输出此类:label___1nGy active___1Jur tab___Le7N tab 是我正在传递的 className 道具。 labelactive 类来自库。我想在active 上应用一组不同的样式,比如.tab.active,其中tab 指的是我创建的样式,active 匹配库创建的生成选择器,但不知道该怎么做这与 css 模块。我需要重写这个动态选择器:.label___1nGy.active___1Jur

[]]2 []3

【问题讨论】:

你能给我们看一个你的代码的小例子吗? 我想修改 react 工具箱组件比覆盖动态生成的类名更容易......或者你可以使用 React Toolbox Webpack Loader github.com/react-toolbox/react-toolbox#customization 感谢您的回复。我已经看过加载器并且当然打算使用它,但是我看到这种情况经常发生,并且希望避免修改库。我想知道 css-modules 本身是否为这个问题提供了一些解决方案,例如 :globalcompose 关键字 通常你会从.tab类组成.active类。但是 react 工具箱组件没有提供必要的 api 来设置你自己的activeClassname prop。 【参考方案1】:

旧帖子但仍然相关,因此添加答案以帮助有类似问题的人

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

在https://github.com/react-toolbox/react-toolbox#customizing-components阅读他们对这个主题更深入的github文档

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

在您的情况下,除了为选项卡传递 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 的装饰器,我建议也阅读一下,因为它解释了默认值是如何与您的覆盖更深入地组合的,包括他们使用的不同合并策略

【讨论】:

【参考方案2】:

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

如果维护者不同意或者您需要快速执行此操作,那么您可以很容易地添加自己的活动 className,因为您的实现组件正在管理索引状态:

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>
    );
  

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

【讨论】:

【参考方案3】:

我有一个类似的案例,我是这样解决的:

import classNames from 'classnames';

...

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

return <div className=elementClassNames />

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

更简洁的方法可能是:

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

【讨论】:

【参考方案4】:

组样式加载器

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

配置加载器

    安装加载器

    npm install --save-dev group-style-loader
    

    在你的 webpack 设置中配置加载器

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

您只需将它放在style-loadermini-css-extract-plugin 加载程序之前。

覆盖组件的样式

下一个示例展示了如何从 App 组件中覆盖 Card 组件的样式。

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

card.css

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


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


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

唯一的区别是在卡片组件中,你要使用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组件的自定义样式987654330@。所有使用此分隔符的类都将被分组到样式对象的 card 属性中。

app.jsx

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


.list 
  display: flex;


.card_title 
  color: blue;


.card_summary 
  color: green;

最后,只需要通过它的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>
  );

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

您可以在其repository 中查看有关如何使用group-style-loader 的完整说明。

【讨论】:

【参考方案5】:

fileName.css 中的技巧

在声明className后添加className-active

.className
  background: white;


.className-active
  background: black;


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

div 总是黑色的

【讨论】:

以上是关于CSS 模块、React 和覆盖 CSS 类的主要内容,如果未能解决你的问题,请参考以下文章

在 React 中使用 CSS Modules

如何覆盖prime-react组件CSS样式?

React 如何避免 css 覆盖其他组件? [复制]

我的 CSS 在 React 项目中被 Bootstrap 覆盖

尝试在 React 中将 CSS 覆盖功能转换为 JSS

覆盖 index.html css react 项目