【问题标题】:How to dynamically add a class to manual class names?如何动态地将类添加到手动类名中?
【发布时间】:2016-07-12 14:08:31
【问题描述】:

我需要将动态类添加到常规类列表中,但不知道如何(我正在使用 babel),如下所示:

<div className="wrapper searchDiv {this.state.something}">
...
</div>

有什么想法吗?

【问题讨论】:

  • 关于 reactjs 样式最佳实践的有用答案link

标签: css reactjs


【解决方案1】:

你可以这样做,普通的 JavaScript:

className={'wrapper searchDiv ' + this.state.something}

或字符串模板版本,带反引号:

className={`wrapper searchDiv ${this.state.something}`}

这两种类型当然都是 JavaScript,但第一种模式是传统的。

无论如何,在 JSX 中,任何用大括号括起来的东西都会作为 JavaScript 执行,所以你基本上可以在那里做任何你想做的事情。但是将 JSX 字符串 花括号组合起来是不可取的属性。

【讨论】:

  • 如果有多个类怎么办?
  • 在多个动态类的情况下,所有动态类都必须来自状态,即不能使用element.classList.add("my-class");因此允许:className={`wrapper searchDiv ${this.state.something ? "my-class " : ""} ${this.state.somethingElse ? "my-other-class " : ""}`}
  • className={'wrapper searchDiv} + this.state.isTrue ? 'my-class' : ' ' 这不起作用。谁能告诉我为什么?
  • @kryptokinght 你可以试试className={'wrapper searchDiv ' + (this.state.isTrue ? 'my-class' : ' ')}
【解决方案2】:

根据随着项目的增长您需要添加多少动态类,可能值得查看 JedWatson 在 GitHub 上的 classnames 实用程序。它允许您将条件类表示为一个对象,并返回那些评估为真的类。

以 React 文档为例:

render () {

var btnClass = classNames({
  'btn': true,
  'btn-pressed': this.state.isPressed,
  'btn-over': !this.state.isPressed && this.state.isHovered
});

return <button className={btnClass}>I'm a button!</button>;

} 

由于 React 会在状态更改时触发重新渲染,因此您的动态类名称会自然处理并与组件的状态保持同步。

【讨论】:

  • 在这么简单的事情上使用类名实在是太过分了。避免使用它并选择 dannyjolie 的简单答案
  • 你确定这是一件简单的事情吗?您几乎总是希望对应用于元素的类进行细粒度的完全控制。
  • @checklist 否则我会争辩说,类名包在 Gzipping 之前是 1.1kB(在 Gzipping 之后是半kB),没有依赖关系,并且为类名操作提供了更简洁的 API。当 API 更具表现力时,没有必要过早地优化这么小的东西。使用标准字符串操作时,您必须记住在每个条件类名之前或每个标准类名之后考虑空格。
  • classNames 很棒,我发现随着组件的复杂性增加,读取、添加和修复道具比手动操作更容易。
【解决方案3】:

一个简单的可能语法是:

<div className={`wrapper searchDiv ${this.state.something}`}>

【讨论】:

    【解决方案4】:

    这是 Dynamic className 的最佳选择,只需像我们在 Javascript 中那样做一些连接。

         className={
            "badge " +
            (this.state.value ? "badge-primary " : "badge-danger ") +
            " m-4"
          }
    

    【讨论】:

    • 这是没有任何掉毛问题的最佳解决方案。像魅力一样工作。谢谢。
    【解决方案5】:

    别想这么复杂的解决方案。

    这是解决您问题的最简单方法。

    <div className={`wrapper searchDiv ${this.state.something}`}>
       ...
    </div>
    

    【讨论】:

      【解决方案6】:

      使用钩子试试这个:

      const [dynamicClasses, setDynamicClasses] = React.useState([
          "dynamicClass1", "dynamicClass2"
      ]);
      

      并将其添加到 className 属性中:

      <div className=`wrapper searchDiv ${[...dynamicClasses]}`>
      ...
      </div>
      

      添加类:

          const addClass = newClass => {
             setDynamicClasses([...dynamicClasses, newClass])
          }
      

      删除类:

              const deleteClass= classToDelete => {
      
                 setDynamicClasses(dynamicClasses.filter(class = > {
                   class !== classToDelete
                 }));
      
              }
      

      【讨论】:

      • ... 扩展运算符实际上会通过 , 逗号默认加入字符串。例如wrapper searchDiv ${[...'c','as']} => "wrapper searchDiv c,as"
      【解决方案7】:

      如果您需要根据状态条件出现的样式名称,我更喜欢使用这种结构:

      <div className={'wrapper searchDiv' + (this.state.something === "a" ? " anotherClass" : "")'}>
      

      【讨论】:

        【解决方案8】:

        您可以使用this npm 包。它处理所有事情,并具有基于变量或函数的静态和动态类的选项。

        // Support for string arguments
        getClassNames('class1', 'class2');
        
        // support for Object
        getClassNames({class1: true, class2 : false});
        
        // support for all type of data
        getClassNames('class1', 'class2', ['class3', 'class4'], { 
            class5 : function() { return false; },
            class6 : function() { return true; }
        });
        
        <div className={getClassNames({class1: true, class2 : false})} />
        

        【讨论】:

          【解决方案9】:
          getBadgeClasses() {
              let classes = "badge m-2 ";
              classes += (this.state.count === 0) ? "badge-warning" : "badge-primary";
              return classes;
          }
          
          <span className={this.getBadgeClasses()}>Total Count</span>
          

          【讨论】:

            【解决方案10】:
            className={css(styles.mainDiv, 'subContainer')}
            

            此解决方案已在 React SPFx 中进行了尝试和测试。

            同时添加导入语句:

            import { css } from 'office-ui-fabric-react/lib/Utilities';
            

            【讨论】:

              【解决方案11】:

              如果您使用的是 css 模块,这对我有用。

              const [condition, setCondition] = useState(false);
              
              \\ toggle condition
              
              return (
                <span className={`${styles.always} ${(condition ? styles.sometimes : '')`}>
                </span>
              )
              

              【讨论】:

              • 抱歉,打错了。我的意思是使用状态。已编辑
              【解决方案12】:
              const ClassToggleFC= () =>{
                
                const [isClass, setClass] = useState(false);
              
                const toggle =() => {
                     setClass( prevState => !prevState)
                }
                
                return(
                    <>
                      <h1 className={ isClass ? "heading" : ""}> Hiii There </h1>
                     <button onClick={toggle}>Toggle</button>
                    </>
                 )
              
              }
              
              

              我只是创建了一个函数组件。在里面我取一个状态并设置初始值为 false..

              我有一个切换状态的按钮..

              每当我们更改状态重新渲染组件时,如果状态值 (isClass) 为 false,h1 的 className 应为“”,如果状态值 (isClass) 为 true,h1 的 className 为“heading”

              【讨论】:

              • 您好,请您用几句话解释一下您的解决方案如何/为何有效。虽然对于专家来说“真相可能在代码中”,但对于许多访问者来说,一些有用的话是很有价值的。谢谢!
              【解决方案13】:

              尽管上面所有的答案都很好,但引起我注意的是字符串插值解决方案。所以我想提出一种不同的方法来使用自定义StringBuilder

              这是实现。

              class StringBuilder {
                static Builder() {
                  class Builder {
                    constructor() {
                      this.bucket = [];
                    }
              
                    append(str) {
                      if (str !== null) {
                        this.bucket.push(str);
                      }
                      return this;
                    }
              
                    build() {
                      return this.bucket.join(' ');
                    }
                  }
                  return new Builder();
                }
              }
              

              然后你就可以像这样在组件中使用它。

              const Field = (props) => {
                const { label } = props;
              
                const [hasFocus, setFocus] = useState(false);
              
                const labelClasses = new StringBuilder.Builder()
                  .append('form-control')
                  .append(hasFocus ? 'has-focus' : null)
                  .build();
              
                const turnOnFocus = () => setFocus(true);
                const turnOffFocus = () => setFocus(false);
              
                return (
                  <div onClick={turnOnFocus} onBlur={turnOffFocus} className="form-group">
                    <input
                      type="text"
                      defaultValue=""
                      onChange={setValue}
                    />
                    <label className={labelClasses}>{label}</label>
                  </div>
                );
              };
              

              一般来说,如果您有更多需要动态 CSS 类的元素,您可以为该特定元素实例化另一个构建器。此外,如果该类出现在具有相同逻辑的多个元素中,则解决方案是将该逻辑提取到方法或函数中。

              【讨论】:

                【解决方案14】:

                你可以简单地使用条件来应用你想要的特定类

                <div className=`wrapper searchDiv ${this.state.something ? "class that you want" : ""}`>
                

                如果你想使用 makeStyle 类,你可以像这样使用它

                <div className=`wrapper searchDiv ${this.state.something ? classes.specifiedClass : ""}`>
                
                

                【讨论】:

                • 你应该使用大括号括起来反引号
                猜你喜欢
                • 1970-01-01
                • 2011-01-15
                • 1970-01-01
                • 2016-12-20
                • 2017-01-01
                • 2015-04-14
                • 2010-10-13
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多