如何向ReactJS组件添加多个类


345

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

我试图将多个类添加到className每个属性li

<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',并且它们之间也应留有空格。
Fadeoc Khaos


1
为什么不classNames={{foo: true, bar: true, baz: false}}classNames={["foo", "bar"]}只是工作
Peter V.Mørch

Answers:


221

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

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

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

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


187
太糟糕了,您只需要引入一个类名库即可向一个元素添加两个类:(
user959690

4
@ user959690这是一个示例。当您经常执行这些操作并且对于何时需要应用类或不需要应用类具有复杂的逻辑时,该库非常有用。如果您正在做简单的事情,那么请确保只使用模板,但是每种情况都不尽相同,读者应为他们的工作选择合适的工具。
杰克

7
@ user959690值得注意的是,NPM现在在使用Webpack时安装它,因此import classNames from 'classnames'可以在组件中使用className={classNames(classes.myFirstClass, classes.mySecondClass)}
Hooligancat

5
无需使用外部库,请参阅下面的答案。
戴维斯

1
图书馆还有其他优点: var btnClass = classNames({ btn: true, 'btn-pressed': this.state.isPressed, 'btn-over': !this.state.isPressed && this.state.isHovered }); return <button className={btnClass}>{this.props.label}</button>;
AmitJS94 '19

394

我使用ES6 模板文字。例如:

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'}`} />

157
另外:<input className={`class1 ${class2}`}>
Cody Moniz

3
@unyo请发表您的评论作为答案,以便我投票赞成。它非常值得。我一直在找一个小时来做​​这样简单的事情,现在我发现它被埋没了。谢谢。
Souvik Ghosh

结果是<input class=" form-control input-lg round-lg" />。请注意开始时的多余空间。这是有效的,但很难看。甚至react FAQ也建议使用另一种方法或使用classnames包:reactjs.org/docs/faq-styling.html
Nakedible,

我无法理解为什么您要导入一个库(如已接受的答案)以设置一些可以使用Vanilla JavaScript进行设置的类,无论如何,这是一种更高效,更简洁,更易读的解决方案。
马库斯·帕森斯

2
这是正确的答案。如“正确”答案中所建议的那样使用依赖项是过大的。
TheDarkIn1978 '19

171

只需使用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]}
Doug Wilhelm

1
@DougWilhelm我认为不起作用。它隐式调用toString并创建一个用逗号分隔的类列表。github.com/facebook/react/issues/3138
0xcaff

6
好的使用className={[listOfClasses].join(' ')}它对我有用,谢谢!
阿拉·埃丁

97

康卡特

不用花哨我正在使用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">

换句话说,两种风格

有条件的

如果将相同的想法与if一起使用,将很容易

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

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

1
这对我有用,还有'-'名称,即:<nav className = {styles.navbar +“” + styles ['navbar-default']}>
Flinkman

大声笑,我crack我的头,答案很简单::D。顺便说一句,这也可以与CSS加载程序模块一起使用
GusDeCooL

这样做的问题是您不能有可选类(如果未定义,则不会添加),因此要确定您的类不为null(非可选),这取决于您的枯萎。在可选的情况下,没有比class()这样的助手更好的了。我们可以将三元数与诸如className={slider $ {className?`$ {className} : ''}}``。但这很多。[注意:“某事” +未定义=“某事未尽”。js动态转换。
Mohamed Allal '18

当然可以,只需在上面声明一个变量并有条件地使用它即可:)
Jamie Hutber

42

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

<input className={`class1 ${class2}`}>

1
这几乎对我有用,我也只需要插补class1并且没有更多错误,所以看起来像这样 <input className={`${class1} ${class2}`}>
Kingston Fortune

35

您可以使用多个类名创建一个元素,如下所示:

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

自然,您可以使用包含类名的字符串,并操纵该字符串来更新元素的类名。

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

1
你测试了吗?我做到了:)
乌鸦

是的,我做到了。实际上,我经常使用它,但只是看到并纠正了一个错字。当然,第一行中包含类名称的字符串必须使用"代替'。对于那个很抱歉。
nightlyop '16

20

这是使用ES6的方法:

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

您可以列出多个类和条件,还可以包括静态类。无需添加其他库。

祝好运 ;)


2
考虑到所有额外的空格,这将导致非常难看的HTML。
赤裸裸的

2
不必那样写。这只是一个更好地说明解决方案的示例。并且始终在生产中使用
最小

18

香草JS

无需外部库-只需使用ES6 模板字符串

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

Vanilla JS不是ES6。但是我喜欢你的榜样。
RyanNerd

8
@RyanNerd您是说“ ES6不是香草JS”吗?无论如何,这是因为Vanilla js的意思是没有任何框架的javascript。ES6是javascript的较新版本。- stackoverflow.com/a/20435685/5111113
休·戴维斯

答案没有错,但可以改进很多。例如,其他所有人都添加了有关状态的示例。
JGallardo

10

也许类名可以帮助您。

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

1
您能否使该示例更有用。
JGallardo

9

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

我个人使用

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

要么

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

如果需要有条件地添加或删除类,则使用第二个。


1
这两种方法只会增加一个类。
TrickOrTreat

6

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

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

6

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

如果导入任何CSS,则可以按照以下方式进行:方式1:

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>




4

晚到派对了,但是为什么要使用第三方解决这个简单的问题呢?

您可以按照@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中,其中保留了所有常用方法。如此简单的功能,我避免使用第3方来保持控制

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

3

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

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

这将导致:

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


2

使用facebook的TodoTextInput.js示例

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代码替换类名看起来像这样:

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} />
    )
  }

2

如果您不想导入另一个模块,则此功能的作用类似于该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]) => { if (flag) arr.push(cls); return arr }, [] ).join(" ") }
ЕвгенийСавичев


1

我就是做这个的:

零件:

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

调用组件:

<Button className = 'hashButton free anotherClass' />

1

我正在使用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),并且不起作用,仅适用头等舱-没有警告或抱怨。
Juan Lanus

1

使用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> 

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

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


0

我使用rc-classnames包。

// ES6
import c from 'rc-classnames';

// CommonJS
var c = require('rc-classnames');

<button className={c('button', {
  'button--disabled': isDisabled,
  'button--no-radius': !hasRadius
})} />

您可以添加任何格式的类(数组,对象,参数)。数组或参数中的所有真实值加上对象中等于true合并在一起的键。

例如:

ReactClassNames('a', 'b', 'c') // => "a b c"
ReactClassNames({ 'a': true, 'b': false, c: 'true' }) // => "a c"
ReactClassNames(undefined, null, 'a', 0, 'b') // => "a b"

0

bind classNames将css模块导入到组件中。

import classNames from 'classnames'; 
import * as styles from './[STYLES PATH];
const cx = classNames.bind(styles); 

classnames提供了以声明方式声明classNameReact元素的功能。

例如:

<div classNames={cx(styles.titleText)}> Lorem </div>

<div classNames={cx('float-left')}> Lorem </div> // global css declared without css modules
<div classNames={cx( (test === 0) ?
             styles.titleText : 
             styles.subTitleText)}>  Lorem </div> // conditionally assign classes

<div classNames={cx(styles.titleText, 'float-left')}> Lorem </div> //combine multiple classes

0

我通常这样使用:(以您为例)

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

当涉及到JSX时(通常),我们有一些json ...比您循环它的... componentmap,加上一些条件检查是否存在json属性以根据JSON中的属性值呈现类名称。在下面的示例中,component_colorcomponent_dark_shade 是来自component.map()的属性

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

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


0

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

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

const buttonClasses = [
    "Button", 
    disabled ? "disabled" : null,
    active ? "active" : null
].filter((class) => class).join(" ")

<button className={buttonClasses} onClick={onClick} disabled={disabled ? disabled : false}>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.