【问题标题】:How to add multiple classes to a ReactJS Component?如何向 ReactJS 组件添加多个类?
【发布时间】:2016-04-03 23:19:33
【问题描述】:

我是 ReactJS 和 JSX 的新手,我对下面的代码有一点问题。

我正在尝试为每个liclassName 属性添加多个类:

<li key={index} className={activeClass, data.class, "main-class"}></li>

我的 React 组件是:

var AccountMainMenu = React.createClass({
  getInitialState: function() {
    return { focused: 0 };
  },

  clicked: function(index) {
    this.setState({ focused: index });
  },

  render: function() {
    var self = this;
    var accountMenuData = [
      {
        name: "My Account",
        icon: "icon-account"
      },
      {
        name: "Messages",
        icon: "icon-message"
      },
      {
        name: "Settings",
        icon: "icon-settings"
      }
    /*{
        name:"Help &amp; Support &nbsp; <span class='font-awesome icon-support'></span>(888) 664.6261",
        listClass:"no-mobile last help-support last"
      }*/
    ];

    return (
      <div className="acc-header-wrapper clearfix">
        <ul className="acc-btns-container">
          {accountMenuData.map(function(data, index) {
            var activeClass = "";

            if (self.state.focused == index) {
              activeClass = "active";
            }

            return (
              <li
                key={index}
                className={activeClass}
                onClick={self.clicked.bind(self, index)}
              >
                <a href="#" className={data.icon}>
                  {data.name}
                </a>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
});

ReactDOM.render(<AccountMainMenu />, document.getElementById("app-container"));

【问题讨论】:

  • 我在这里找到了一个简短的答案stackoverflow.com/a/36209517/4125588,只需使用 JavaScript 加入这个类,静态或动态,使用 '+' 运算符,记得在除第一个类之外的类之前插入'',如HTML中真正的类应该像'ab c',它们之间也是空格。
  • 为什么classNames={{foo: true, bar: true, baz: false}}classNames={["foo", "bar"]} 不只是工作
  • 那你为什么只为 li 元素分配一个类名“active”?
  • 可以查看npmjs.com/package/@ivanhanak_com/react-join-classnames,这里基本上可以使用&lt;div className={classes(isTrue &amp;&amp; "willRenderThisClass")} /&gt;

标签: javascript css reactjs ecmascript-6


【解决方案1】:

我使用ES6 template literals。例如:

const error = this.state.valid ? '' : 'error'
const classes = `form-control round-lg ${error}`

然后渲染它:

<input className={classes} />

单行版本:

<input className={`form-control round-lg ${this.state.valid ? '' : 'error'}`} />

【讨论】:

  • 这导致&lt;input class=" form-control input-lg round-lg" /&gt;。请注意开头的额外空间。这是有效的,但丑陋。甚至 react FAQ 推荐另一种方式或使用类名包:reactjs.org/docs/faq-styling.html
  • 我无法理解你为什么要导入一个库(如已接受的答案)来设置一些可以使用 Vanilla JavaScript 设置的类,这是一种更高效、更清洁、更易读的无论如何,解决方案。
  • 这是正确答案。按照“正确”答案中的建议为此使用依赖项是过分的。
  • 我一直很喜欢这个答案,但不喜欢最后的额外空间,以防错误值。您可以使用trim() 轻松避免。
  • @CodyMoniz 这个答案引导我朝着正确的方向前进!我有一种情况,我需要添加多个“变量”类。 className={ `${ props.variable } ${ props.variabletwo }` } 工作!几个小时不知道如何搜索这个,通过这个答案补救。
【解决方案2】:

当决定(不)使用的类需要大量逻辑时,我使用classnames。一个过于简单的例子

...
    var liClasses = classNames({
      'main-class': true,
      'activeClass': self.state.focused === index
    });

    return (<li className={liClasses}>{data.name}</li>);
...

也就是说,如果您不想包含依赖项,那么下面有更好的答案。

【讨论】:

  • 太糟糕了,你不得不引入一个类名库来为一个元素添加两个类:(
  • @user959690 这是一个例子。当你经常做这些事情并且你对何时需要应用类有复杂的逻辑时,这个库非常好。如果您正在做一些简单的事情,那么请确保只使用模板,但每种情况都不同,读者应该为他们的工作选择正确的工具。
  • @user959690 值得注意的是现在是installed by NPM when using Webpack,所以import classNames from 'classnames'然后在一个组件中使用className={classNames(classes.myFirstClass, classes.mySecondClass)}
  • 不需要使用外部库,请看下面我的回答。
  • 库还有其他优点:var btnClass = classNames({ btn: true, 'btn-pressed': this.state.isPressed, 'btn-over': !this.state.isPressed &amp;&amp; this.state.isHovered }); return &lt;button className={btnClass}&gt;{this.props.label}&lt;/button&gt;;
【解决方案3】:

只需使用 JavaScript。

<li className={[activeClass, data.klass, "main-class"].join(' ')} />

如果要在对象中添加基于类的键和值,可以使用以下方法:

function classNames(classes) {
  return Object.entries(classes)
    .filter(([key, value]) => value)
    .map(([key, value]) => key)
    .join(' ');
}

const classes = {
  'maybeClass': true,
  'otherClass': true,
  'probablyNotClass': false,
};

const myClassNames = classNames(classes);
// Output: "maybeClass otherClass"

<li className={myClassNames} />

甚至更简单:

const isEnabled = true;
const isChecked = false;

<li className={[isEnabled && 'enabled', isChecked && 'checked']
  .filter(e => !!e)
  .join(' ')
} />
// Output:
// <li className={'enabled'} />

【讨论】:

  • 这行对我有用:className={['terra-Table', medOrder.resource.status]}
  • @DougWilhelm 我认为这行不通。它隐式调用 toString 并创建一个逗号分隔的类列表。 github.com/facebook/react/issues/3138
  • 使用className={[listOfClasses].join(' ')}的好主意,谢谢!
  • 我更喜欢更性感的 className={[activeClass, data.klass, "main-class"].filter(Boolean).join(' ')}
【解决方案4】:

连接

不用花哨,我正在使用 CSS 模块,这很简单

import style from '/css/style.css';

<div className={style.style1+ ' ' + style.style2} />

这将导致:

<div class="src-client-css-pages-style1-selectionItem src-client-css-pages-style2">

换句话说,两种风格

条件

如果使用相同的想法很容易

const class1 = doIHaveSomething ? style.style1 : 'backupClass';

<div className={class1 + ' ' + style.style2} />

ES6

过去一年左右我一直在使用模板文字,所以我觉得它值得一提,我觉得它非常有表现力且易于阅读:

`${class1} anotherClass ${class1}`

【讨论】:

  • 这对我有用,还有 '-' 名称,即:
  • 大声笑,我的脑袋都裂开了,答案很简单:D。顺便说一句,这也适用于 CSS 加载器模块
  • 问题是你不能有可选的类(如果未定义,那么它不会被添加),所以它取决于你确定你的类不为空(不是可选的)。在可选的情况下,没有比 classes() 这样的助手更好的了。我们可以使用带有模板的三元组className={slider${className? ` ${className}: ''}}``。但是很多。 [注:'某事'+未定义='某事欠佳'。 js动态转换。
  • 当然可以,只需在上面声明一个变量并有条件地使用它:)
  • 忘记了一切实际上只是 JavaScript,从未尝试过。谢谢,帮了大忙。
【解决方案5】:

这可以通过 ES6 模板文字来实现:

<input className={`base-input-class ${class1} ${class2}`}>

(为清楚起见进行了编辑)

【讨论】:

  • 这几乎对我有用,我只需要插入 class1 并且没有更多错误,所以它看起来像这样 &lt;input className={`${class1} ${class2}`}&gt;
  • 所以如果class1 不存在,你最终会得到中间那个大的空白。
  • 是的,这会以空格结尾。如果您不想要空格,可以使用:&lt;input className={['base-input-class', class1, class2].filter(x =&gt; x).join(' ')} /&gt;
【解决方案6】:

您可以像这样创建具有多个类名的元素:

<li className="class1 class2 class3">foo</li>

当然,您可以使用包含类名的字符串并操作此字符串来更新元素的类名。

var myClassNammes = 'class1 class2 class3';
...
<li className={myClassNames}>foo</li>

【讨论】:

  • 你测试过这个吗?我做到了:)
  • 是的,我做到了。实际上,我经常使用它,但只是看到并纠正了一个错字。当然,第一行中包含类名的字符串必须使用" 而不是'。对此感到抱歉。
【解决方案7】:

这就是使用 ES6 的方法:

className = {`
      text-right
      ${itemId === activeItemId ? 'active' : ''}
      ${anotherProperty === true ? 'class1' : 'class2'}
`}

您可以列出多个类和条件,也可以包含静态类。无需添加额外的库。

祝你好运;)

【讨论】:

  • 考虑到所有额外的空白,这会导致 HTML 非常难看。
  • 没必要这么写。这只是一个更好地解释解决方案的示例。并且总是在生产中你有缩小版本:)
  • 字符串文字在生产中不会被缩小。
【解决方案8】:

我认为我们不需要使用外部包来添加多个类。

我个人使用

<li className={`li active`}>Stacy</li>

<li className={`li ${this.state.isActive ? 'active' : ''}`}>Stacy<li>

<li className={'li ' + (this.state.isActive ? 'active' : '') }>Stacy<li>

第二个和第三个,以防您需要有条件地添加或删除类。

【讨论】:

  • 这将只添加一个类。
  • @TrickOrTreat 不正确。上面所有的例子都会添加两个类(假设 isActive 为真)。
  • 为什么除了这个之外还有其他答案?
【解决方案9】:

原版 JS

不需要外部库 - 只需使用 ES6 template strings

<i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/>

【讨论】:

  • Vanilla JS 不是 ES6。但我确实喜欢你的例子。
  • @RyanNerd 你的意思是“ES6 不是 vanilla JS”吗?无论如何,它是,因为 vanilla js 意味着没有任何框架的 javascript。 ES6 是 javascript 的更新版本。 - stackoverflow.com/a/20435685/5111113
  • 不是一个错误的答案,但可以改进很多。例如,其他人都添加了有关状态的示例。
【解决方案10】:

一般人都喜欢

<div className={  `head ${style.class1} ${Style.class2}`  }><div>

<div className={  'head ' + style.class1 + ' ' + Style.class2 }><div>

<div className={  ['head', style.class1 , Style.class2].join(' ')  }><div>

但你可以选择创建一个函数来完成这项工作

function joinAll(...classes) {
  return classes.join(" ")
}

然后这样称呼它:-

<div className={joinAll('head', style.class1 , style.class2)}><div>

【讨论】:

    【解决方案11】:

    也许classnames可以帮到你。

    var classNames = require('classnames');
    classNames('foo', {'xx-test': true, bar: false}, {'ox-test': false}); // => 'foo xx-test'
    

    【讨论】:

    • 你能让这个例子更有用吗?
    • 我相信 clsx(npmjs.com/package/clsx) 是类名的一个很好的替代品。
    【解决方案12】:

    您可以执行以下操作:

    <li key={index} className={`${activeClass} ${data.class} main-class`}></li>
    

    一个简短的解决方案,希望对您有所帮助。

    【讨论】:

    • IMO 这是最好的答案! :)
    【解决方案13】:

    可以通过https://www.npmjs.com/package/clsx 完成:

    https://www.npmjs.com/package/clsx

    首先安装它:

    npm install --save clsx
    

    然后将其导入到你的组件文件中:

    import clsx from  'clsx';
    

    然后在你的组件中使用导入的函数:

    <div className={ clsx(classes.class1, classes.class2)}>
    

    【讨论】:

      【解决方案14】:

      只要添加,我们就可以过滤掉空字符串。

      className={[
          'read-more-box',
          this.props.className,
          this.state.isExpanded ? 'open' : 'close',
      ].filter(x => !!x).join(' ')}
      

      【讨论】:

        【解决方案15】:

        你可以像这样创建一个具有多个类名的元素,我尝试了这两种方式,它工作正常......

        如果您导入任何 css,那么您可以按照以下方式进行操作: 方式一:

        import React, { Component, PropTypes } from 'react';
        import csjs from 'csjs';
        import styles from './styles';
        import insertCss from 'insert-css';
        import classNames from 'classnames';
        insertCss(csjs.getCss(styles));
        export default class Foo extends Component {
          render() {
            return (
              <div className={[styles.class1, styles.class2].join(' ')}>
                { 'text' }
              </div>
            );
          }
        }
        

        方式2:

        import React, { Component, PropTypes } from 'react';
        import csjs from 'csjs';
        import styles from './styles';
        import insertCss from 'insert-css';
        import classNames from 'classnames';
        insertCss(csjs.getCss(styles));
        export default class Foo extends Component {
          render() {
            return (
              <div className={styles.class1 + ' ' + styles.class2}>
                { 'text' }
              </div>
            );
          }
        }
        

        **

        如果您将 css 作为内部应用:

        const myStyle = {
          color: "#fff"
        };
        
        // React Element using Jsx
        const myReactElement = (
          <h1 style={myStyle} className="myClassName myClassName1">
            Hello World!
          </h1>
        );
        
        ReactDOM.render(myReactElement, document.getElementById("app"));
        .myClassName {
          background-color: #333;
          padding: 10px;
        }
        .myClassName1{
          border: 2px solid #000;
        }
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.production.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.production.min.js"></script>
        <div id="app">
          
        </div>

        【讨论】:

        • .join(' ') 很好。但我们可以避免这种情况并使用模板字符串 className={${styles.class1}${styles.class2}}
        【解决方案16】:

        更多课程添加

        ... className={`${classes.hello} ${classes.hello1}`...
        

        【讨论】:

          【解决方案17】:

          我知道这是一个迟到的答案,但我希望这会对某人有所帮助。

          假设您在 css 文件中定义了以下类 'primary'、'font-i'、'font-xl'

          • 第一步是导入 CSS 文件。
          • 那么

          &lt;h3 class = {` ${'primary'} ${'font-i'} font-xl`}&gt; HELLO WORLD &lt;/h3&gt;

          会成功的!

          欲了解更多信息:https://www.youtube.com/watch?v=j5P9FHiBVNo&list=PLC3y8-rFHvwgg3vaYJgHGnModB54rxOk3&index=20

          【讨论】:

            【解决方案18】:

            这似乎对我有用

            <Link className={[classes.button, classes.buttonFirst]}>
            

            【讨论】:

            • 在 TypeScript 中这给了我:Type 'string[]' is not assignable to type 'string'.
            【解决方案19】:

            聚会迟到了,为什么要使用第三方来解决这么简单的问题?

            你可以像@Huw Davies 提到的那样做——最好的方法

            1. <i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/>
            2. <i className={[styles['foo-bar-baz'], 'fa fa-user', 'fa-2x'].join(' ')}
            

            两者都很好。但是对于大型应用程序而言,编写可能会变得复杂。为了使其最佳化,我做了上述相同的事情,但把它放在一个帮助类中

            使用我下面的辅助函数,允许我将逻辑分开以供将来编辑,并且还为我提供了多种添加类的方法

            classNames(styles['foo-bar-baz], 'fa fa-user', 'fa-2x')
            

            classNames([styles['foo-bar-baz], 'fa fa-user', 'fa-2x'])
            

            这是我下面的辅助函数。我把它放在了一个 helper.js 中,我保留了我所有的常用方法。作为一个如此简单的功能,我避免使用 3rd 方来保持控制

            export function classNames (classes) {
                if(classes && classes.constructor === Array) {
                    return classes.join(' ')
                } else if(arguments[0] !== undefined) {
                    return [...arguments].join(' ')
                }
                return ''
            }
            

            【讨论】:

              【解决方案20】:

              您可以使用数组,然后使用空格连接它们。

              <li key={index} className={[activeClass, data.class, "main-class"].join(' ')}></li>
              

              这将导致:

              <li key={index} class="activeClass data.class main-class"></li>
              

              【讨论】:

                【解决方案21】:

                创建一个这样的函数

                function cssClass(...c) {
                  return c.join(" ")
                }
                

                在需要时调用它。

                <div className={cssClass("head",Style.element,"black")}><div>
                

                【讨论】:

                  【解决方案22】:

                  当我有许多不同的课程时,我发现以下内容很有用。

                  过滤器删除任何null 值,连接将所有剩余值放入空格分隔的字符串中。

                  const buttonClasses = [
                      "Button", 
                      disabled ? "disabled" : null,
                      active ? "active" : null
                  ].filter((class) => class).join(" ")
                  
                  <button className={buttonClasses} onClick={onClick} disabled={disabled ? disabled : false}>
                  

                  【讨论】:

                    【解决方案23】:

                    使用facebook's TodoTextInput.js example

                    render() {
                        return (
                          <input className={
                            classnames({
                              edit: this.props.editing,
                              'new-todo': this.props.newTodo
                            })}
                            type="text"
                            placeholder={this.props.placeholder}
                            autoFocus="true"
                            value={this.state.text}
                            onBlur={this.handleBlur}
                            onChange={this.handleChange}
                            onKeyDown={this.handleSubmit} />
                        )
                      } 
                    

                    用普通的 js 代码替换 classnames 将如下所示:

                    render() {
                        return (
                          <input
                            className={`
                              ${this.props.editing ? 'edit' : ''} ${this.props.newTodo ? 'new-todo' : ''}
                            `}
                            type="text"
                            placeholder={this.props.placeholder}
                            autoFocus="true"
                            value={this.state.text}
                            onBlur={this.handleBlur}
                            onChange={this.handleChange}
                            onKeyDown={this.handleSubmit} />
                        )
                      }
                    

                    【讨论】:

                      【解决方案24】:

                      如果你不想导入另一个模块,这个函数就像classNames 模块一样工作。

                      function classNames(rules) {
                          var classes = ''
                      
                          Object.keys(rules).forEach(item => {    
                              if (rules[item])
                                  classes += (classes.length ? ' ' : '') + item
                          })
                      
                          return classes
                      } 
                      

                      你可以这样使用它:

                      render() {
                          var classes = classNames({
                              'storeInfoDiv': true,  
                              'hover': this.state.isHovered == this.props.store.store_id
                          })   
                      
                          return (
                              <SomeComponent style={classes} />
                          )
                      }
                      

                      【讨论】:

                      • 如果可以对 map 或 reduce 做同样的事情,为什么还要使用闭包呢? function classNames(rules) { return Object.entries(rules) .reduce( (arr, [cls, flag]) =&gt; { if (flag) arr.push(cls); return arr }, [] ).join(" ") }
                      【解决方案25】:

                      使用https://www.npmjs.com/package/classnames

                      从“类名”中导入类名;

                      1. 可以使用逗号分隔的多个类:

                        <li className={classNames(classes.tableCellLabel, classes.tableCell)}>Total</li>
                        
                      2. 可以使用逗号分隔的多个类,用条件分隔:

                        <li className={classNames(classes.buttonArea, !nodes.length && classes.buttonAreaHidden)}>Hello World</li> 
                        

                      使用数组作为类名的道具也可以,但会发出警告,例如

                      className={[classes.tableCellLabel, classes.tableCell]}
                      

                      【讨论】:

                      【解决方案26】:

                      clsx 让这一切变得简单!

                      "clsx 函数可以接受任意数量的参数,每个参数都可以 可以是对象、数组、布尔值或字符串。”

                      -- npmjs.com 上的 clsx 文档

                      导入:

                      import clsx from 'clsx'
                      

                      使用它:

                      <li key={index} className={clsx(activeClass, data.class, "main-class")}></li>
                      

                      【讨论】:

                        【解决方案27】:

                        我使用了这个语法

                            <div
                              className={[
                                "d-inline-flex justify-content-center align-items-center ",
                                withWrapper && `ft-icon-wrapper ft-icon-wrapper-${size}`,
                                wrapperClass,
                              ].join(" ")}
                            >
                              <img
                                className={`ft-icon ft-icon-${size} ${iconClass}`}
                                alt={id}
                                src={icon}
                              />
                            </div>
                        

                        【讨论】:

                        • 已经建议了两种解决方案(连接和模板文字)。请说明您的不同之处
                        【解决方案28】:

                        我就是这样做的:

                        组件:

                        const Button = ({ className }) => (
                          <div className={ className }> </div>
                        );
                        

                        调用组件:

                        <Button className = 'hashButton free anotherClass' />
                        

                        【讨论】:

                          【解决方案29】:

                          我正在使用 React 16.6.3 和 @Material UI 3.5.1,并且能够在 className 中使用数组,例如 className={[classes.tableCell, classes.capitalize]}

                          因此,在您的示例中,以下内容类似。

                          <li key={index} className={[activeClass, data.class, "main-class"]}></li>
                          

                          【讨论】:

                          • 这就是我正在做的(尽管没有 MUI)并且不起作用,只适用于第一类 - 没有警告或抱怨。
                          【解决方案30】:

                          我通常这样使用它:(在你的情况下)

                              <li  key={index} className={
                                  "component " +
                                  `${activeClass? activeClass: " not-an-active-class "}` +
                                  `${data.class? " " + data.class : " no-data-class "}`
                             } />
                          

                          当涉及到 JSX 和(通常)我们有一些 json...而不是你循环它... component.ma​​p,加上一些条件来检查是否json 属性的存在是为了根据 JSON 中的属性值呈现类名。在下面的示例中,component_colorcomponent_dark_shade 是来自 component.map()

                          的属性
                             <div className={
                                  "component " +
                                  `${component_color? component_color: " no-color "}` +
                                  `${component_dark_shade? " " + component_dark_shade : " light "}`
                             }/>
                          

                          输出:&lt;div class="component no-color light" .... 或者:&lt;div class="component blue dark" .... 取决于地图中的值...

                          【讨论】:

                          • 我更喜欢你的解决方案,有以下改动:任何类型的类名(静态、动态、道具)之后都不需要空格:“组件”与“组件”,动态类名使用简单括号也比字符串文字少 3 个字符:${conditionalClassname} vs (conditionalClassname),并且会使用接收到的道具类名扩展您的示例,我更喜欢将其与字符串文字一起使用:`${propClassname}` - 注意`和$.
                          • 感谢@Rich 的建议。我同意我们可以肯定地保存一些字符。出于理解此示例/用例的原因,我将其保留为更明显,以免人们对空格感到困惑,但是我喜欢您的建议-非常有意义。谢谢!
                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2020-07-02
                          • 1970-01-01
                          • 1970-01-01
                          • 2014-08-26
                          • 2021-12-09
                          • 2020-07-01
                          相关资源
                          最近更新 更多