Cách thêm nhiều lớp vào Thành phần ReactJS


346

Tôi chưa quen với ReactJS và JSX và tôi gặp một chút vấn đề với mã bên dưới.

Tôi đang cố gắng thêm nhiều lớp vào classNamethuộc tính trên mỗi li:

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

Thành phần React của tôi là:

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

Tôi đã tìm thấy một câu trả lời ngắn gọn ở đây stackoverflow.com/a/36209517/4125588 , chỉ cần sử dụng JavaScript để tham gia các lớp này, tĩnh hoặc động, với toán tử '+', hãy nhớ chèn '' trước các lớp ngoại trừ lớp đầu tiên, như thật lớp trong HTML phải giống như 'ab c', cũng là khoảng cách giữa chúng.
Fadeoc Khaos


1
Tại sao không classNames={{foo: true, bar: true, baz: false}}classNames={["foo", "bar"]}chỉ làm việc ?
Peter V. Mørch

Câu trả lời:


221

Tôi sử dụng tên lớp khi có một lượng logic hợp lý cần thiết để quyết định các lớp sử dụng (không). Một ví dụ quá đơn giản :

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

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

Điều đó nói rằng, nếu bạn không muốn bao gồm một phụ thuộc thì có câu trả lời tốt hơn dưới đây.


188
Điều đó thật tệ khi bạn phải mang vào một thư viện các tên lớp chỉ để thêm hai lớp vào một phần tử :(
user959690

4
@ user959690 Đây là một ví dụ. Thư viện này rất hay khi bạn làm những việc này rất nhiều và bạn có logic phức tạp khi các lớp cần được áp dụng hay không. Nếu bạn đang làm một cái gì đó đơn giản thì chắc chắn chỉ cần sử dụng các mẫu, nhưng mỗi trường hợp là khác nhau và người đọc nên chọn công cụ phù hợp cho công việc của họ.
Jack

7
@ user959690 Điều đáng chú ý là hiện tại nó đã được NPM cài đặt khi sử dụng Webpack , vì vậyimport classNames from 'classnames' sau đó sẽ sử dụng trong một thành phần className={classNames(classes.myFirstClass, classes.mySecondClass)} .
Hooligancat

5
Không cần sử dụng một thư viện bên ngoài, xem câu trả lời của tôi dưới đây.
Huw Davies

1
Thư viện có những lợi thế khác: 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

395

Tôi sử dụng ES6 mẫu chữ . Ví dụ:

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

Và sau đó chỉ hiển thị nó:

<input className={classes} />

Phiên bản một lớp lót:

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

157
Ngoài ra:<input className={`class1 ${class2}`}>
Cody Moniz

3
@unyo Xin vui lòng gửi bình luận của bạn như là một câu trả lời để tôi có thể nâng cao nó. Nó rất xứng đáng với nó. Tôi đã tìm kiếm 1 giờ cho một cái gì đó dễ dàng như thế này, và bây giờ tôi thấy điều này được chôn vùi như một bình luận. Cảm ơn bạn.
Souvik Ghosh

Kết quả này trong <input class=" form-control input-lg round-lg" /> . Hãy lưu ý không gian thêm vào đầu. Điều này là hợp lệ, nhưng xấu xí. Thậm chí phản ứng FAQ còn đề xuất một cách khác hoặc sử dụng gói tên lớp: Reacjs.org/docs/faq-stomme.html
Nakedible

Tôi không thể hiểu tại sao bạn nhập thư viện (như trong câu trả lời được chấp nhận) để chỉ đặt một số lớp có thể được đặt bằng Vanilla JavaScript, đây là một giải pháp hiệu quả hơn, sạch hơn và dễ đọc hơn.
Marcus Parsons

2
Đây là câu trả lời chính xác. Sử dụng một phụ thuộc cho điều này như được đề xuất trong câu trả lời "chính xác" là quá mức cần thiết.
TheDarkIn1978

171

Chỉ cần sử dụng JavaScript.

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

Nếu bạn muốn thêm các khóa và giá trị dựa trên các lớp trong một đối tượng, bạn có thể sử dụng như sau:

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

Hoặc thậm chí đơn giản hơn:

const isEnabled = true;
const isChecked = false;

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

Đây là dòng làm việc cho tôi:className={['terra-Table', medOrder.resource.status]}
Doug Wilhelm

1
@DougWilmus Tôi không nghĩ rằng nó hoạt động. Nó ngầm gọi toString và tạo một danh sách các lớp được phân tách bằng dấu phẩy. github.com/facebook/react/issues/3138
0xcaff

6
Ý tưởng tốt để sử dụng className={[listOfClasses].join(' ')}nó làm việc cho tôi cảm ơn!
Ala Eddine JEBALI

98

Concat

Không cần phải thích tôi đang sử dụng các mô-đun CSS và thật dễ dàng

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

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

Điều này sẽ dẫn đến:

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

Nói cách khác, cả hai phong cách

Điều kiện

Sẽ thật dễ dàng để sử dụng cùng một ý tưởng với if

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

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

1
Điều này hiệu quả với tôi, cùng với tên '-', tức là: <nav className = {Styles.navbar + "" + style ['navbar-default']}>
Flinkman

LOL, tôi bẻ đầu và câu trả lời rất đơn giản: D. Btw alsow này hoạt động với Mô-đun trình tải CSS
GusDeCooL

Vấn đề với điều đó là bạn không thể có các lớp tùy chọn (nếu không được xác định, thì nó sẽ không được thêm vào), vì vậy nó phụ thuộc vào sự khô héo của bạn, bạn chắc chắn rằng lớp của bạn không rỗng (không phải là tùy chọn). Trong trường hợp tùy chọn, không tốt hơn thì một người trợ giúp như các lớp (). chúng ta có thể sử dụng một ternary với các mẫu như className={thanh trượt $ {className không? `$ {className} : ''}}` `. Nhưng nó rất nhiều. [lưu ý: 'cái gì đó' + không xác định = 'cái gì đó chưa hoàn thành'. Js chuyển đổi động.
Mohamed Allal

Chắc chắn bạn có thể, chỉ cần khai báo một biến ở trên và sử dụng nó một cách có điều kiện :)
Jamie Hutber

42

Điều này có thể đạt được với các mẫu chữ ES6:

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

1
điều này gần như làm việc với tôi Tôi chỉ phải nội suy class1 và không có thêm lỗi nào, vì vậy nó trông như thế này <input className={`${class1} ${class2}`}>
Kingston Fortune

35

Bạn có thể tạo một phần tử có nhiều tên lớp như thế này:

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

Đương nhiên, bạn có thể sử dụng một chuỗi chứa tên lớp và thao tác chuỗi này để cập nhật tên lớp của phần tử.

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

1
Bạn đã kiểm tra điều này? Tôi đã làm :)
quạ

Có tôi đã làm. Trên thực tế, tôi đang sử dụng nó khá thường xuyên nhưng chỉ nhìn thấy và sửa lỗi chính tả. Tất nhiên, chuỗi chứa tên lớp trong dòng đầu tiên phải được thực hiện bằng cách sử dụng "thay vì '. Xin lỗi vì điều đó.
nightlyop

20

Đây là cách bạn có thể làm điều đó với ES6:

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

Bạn có thể liệt kê nhiều lớp và điều kiện và bạn cũng có thể bao gồm các lớp tĩnh. Không cần thiết phải thêm một thư viện bổ sung.

Chúc may mắn ;)


2
Điều này dẫn đến HTML rất xấu, xem xét tất cả các khoảng trắng thêm.
Khỏa thân

2
Không cần thiết phải viết như vậy. Đây chỉ là một ví dụ giải thích rõ hơn về giải pháp. Và luôn luôn trong sản xuất, bạn có phiên bản rút gọn :)
Hristo Eftimov

18

Vanilla JS

Không cần thư viện bên ngoài - chỉ cần sử dụng chuỗi mẫu ES6 :

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

Vanilla JS KHÔNG phải là ES6. Nhưng tôi thích ví dụ của bạn.
RyanNerd

8
@RyanNerd Ý bạn là "ES6 không phải là vanilla JS"? Dù sao, đó là, bởi vì vanilla js có nghĩa là javascript mà không có bất kỳ khuôn khổ nào. ES6 là phiên bản mới hơn của javascript. - stackoverflow.com/a/20435685/5111113
Huw Davies

Không phải là một câu trả lời sai nhưng có thể được cải thiện rất nhiều. Ví dụ, mọi người khác đã thêm ví dụ về các tiểu bang.
JGallardo

10

Có lẽ tên lớp có thể giúp bạn.

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

1
Bạn có thể làm cho ví dụ này có thể sử dụng nhiều hơn.
JGallardo

9

Tôi không nghĩ rằng chúng ta cần sử dụng một gói bên ngoài để chỉ thêm nhiều lớp.

Cá nhân tôi sử dụng

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

hoặc là

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

cái thứ hai trong trường hợp bạn cần thêm hoặc loại bỏ các lớp một cách có điều kiện.


1
điều này sẽ chỉ thêm một lớp
TrickOrTreat

6

Chỉ cần thêm, chúng ta có thể lọc ra các chuỗi trống.

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

6

Bạn có thể tạo một phần tử với nhiều tên lớp như thế này, tôi đã thử cả hai cách, nó hoạt động tốt ...

Nếu bạn nhập bất kỳ css nào thì bạn có thể làm theo cách này: Cách 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>
    );
  }
}

cách 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>
    );
  }
}

**

Nếu bạn áp dụng css như nội bộ:

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>


6

Bạn có thể làm như sau:

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

Một giải pháp ngắn và đơn giản, hy vọng điều này sẽ giúp.



4

Đến bữa tiệc muộn, nhưng tại sao lại sử dụng bên thứ ba cho một vấn đề đơn giản như vậy?

Bạn có thể làm như @Huw Davies đã đề cập - cách tốt nhất

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(' ')}

Cả hai đều tốt. Nhưng viết có thể trở nên phức tạp cho một ứng dụng lớn. Để làm cho nó tối ưu, tôi làm những điều tương tự ở trên nhưng đặt nó trong một lớp trợ giúp

Sử dụng chức năng trợ giúp bên dưới của tôi, cho phép tôi tách riêng logic để chỉnh sửa trong tương lai và cũng cho tôi nhiều cách để thêm các lớp

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

hoặc là

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

Đây là chức năng trợ giúp của tôi dưới đây. Tôi đã đặt nó trong helper.js nơi tôi giữ tất cả các phương thức phổ biến của mình. Là một chức năng đơn giản như vậy, tôi tránh sử dụng bên thứ 3 để kiểm soát

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

3

Bạn có thể sử dụng mảng và sau đó nối chúng bằng khoảng trắng.

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

Điều này sẽ dẫn đến:

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

3

Tôi biết đây là một câu trả lời muộn, nhưng tôi hy vọng điều này sẽ giúp được ai đó.

Hãy xem xét rằng bạn đã xác định các lớp sau trong tệp css ' chính ', ' font-i ', ' font-xl '

  • Bước đầu tiên sẽ là nhập tệp CSS.
  • Sau đó

<h3 class = {` ${'primary'} ${'font-i'} font-xl`}> HELLO WORLD </h3>

sẽ làm các mẹo!

Để biết thêm thông tin: https://www.youtube.com/watch?v=j5P9FHiBVNo&list=PLC3y8-rFHvwgg3vaYJgHGnModB54rxOk3&index=20



2

Sử dụng ví dụ TodoTextInput.js của facebook

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

thay thế tên lớp bằng mã jilla vanilla đơn giản sẽ như thế này:

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

Nếu bạn không muốn nhập mô-đun khác, chức năng này hoạt động giống như classNamesmô-đun.

function classNames(rules) {
    var classes = ''

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

    return classes
} 

Bạn có thể sử dụng nó như thế này:

render() {
    var classes = classNames({
        'storeInfoDiv': true,  
        'hover': this.state.isHovered == this.props.store.store_id
    })   

    return (
        <SomeComponent style={classes} />
    )
}

Tại sao sử dụng đóng cửa nếu bạn có thể làm tương tự với bản đồ hoặc giảm? function classNames(rules) { return Object.entries(rules) .reduce( (arr, [cls, flag]) => { if (flag) arr.push(cls); return arr }, [] ).join(" ") }
Евгений Савичев

1

Đó là những gì tôi làm:

Thành phần:

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

Thành phần gọi:

<Button className = 'hashButton free anotherClass' />

1

Tôi đang sử dụng React 16.6.3 và @M vật liệu UI 3.5.1 và có thể sử dụng các mảng trong className như className={[classes.tableCell, classes.capitalize]}

Vì vậy, trong ví dụ của bạn, sau đây sẽ là tương tự.

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

Đây là những gì tôi đã làm (mặc dù không có MUI) và không hoạt động, chỉ áp dụng lớp đầu tiên - không có cảnh báo hoặc khiếu nại.
Juan Lanus

1

Sử dụng https://www.npmjs.com/package/ classnames

nhập tên lớp từ 'tên lớp';

  1. Có thể sử dụng nhiều lớp bằng cách sử dụng comas tách biệt:

    <li className={classNames(classes.tableCellLabel, classes.tableCell)}>Total</li>
  2. Có thể sử dụng nhiều lớp bằng cách sử dụng các khoảng cách

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

Sử dụng mảng làm đạo cụ cho classNames cũng sẽ hoạt động, nhưng đưa ra cảnh báo, ví dụ:

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


0

Tôi sử dụng gói 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
})} />

Bạn có thể thêm các lớp ở bất kỳ định dạng nào (Mảng, Đối tượng, Đối số). Tất cả các giá trị trung thực từ mảng hoặc đối số cộng với các khóa trong các đối tượng bằng nhau để trueđược hợp nhất với nhau.

ví dụ:

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

Tôi bind classNamesđến mô-đun css được nhập vào thành phần.

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

classnames cho khả năng khai báo className cho phần tử React theo cách khai báo.

Ví dụ:

<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

Tôi thường sử dụng nó như thế này: (trong trường hợp của bạn)

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

Khi nói đến JSX và (thông thường), chúng ta có một số json ... hơn là bạn lặp nó ... thành phần . ánh xạ , cộng với một số điều kiện để kiểm tra xem thuộc tính json có tồn tại để hiển thị tên lớp hay không tùy thuộc vào giá trị thuộc tính từ JSON. Trong ví dụ bên dưới thành phần_colorthành phần_dark_shade là các thuộc tính từ thành phần.map ()

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

Đầu ra: <div class="component no-color light" .... Hoặc: <div class="component blue dark" ....tùy thuộc vào các giá trị từ bản đồ ...


0

Khi tôi có nhiều lớp khác nhau, tôi đã thấy những điều sau đây là hữu ích.

Bộ lọc loại bỏ bất kỳ nullgiá trị nào và phép nối đặt tất cả các giá trị còn lại vào một chuỗi được phân tách bằng dấu cách.

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

<button className={buttonClasses} onClick={onClick} disabled={disabled ? disabled : false}>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.