【问题标题】:CSS Modules, React and Overriding CSS ClassesCSS 模块、React 和覆盖 CSS 类
【发布时间】: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。

标签: css css-modules


【解决方案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 覆盖组件的样式。此加载器为您提供了一种简单直观的方式来覆盖组件的样式。

        配置加载器

        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
                      }
                    }
                  ]
                }
              ]
            }
          };
          

        您只需将它放在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 总是黑色的

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-03
            • 1970-01-01
            • 1970-01-01
            • 2019-12-12
            • 2021-11-12
            • 2017-11-03
            相关资源
            最近更新 更多