【问题标题】:React Js conditionally applying class attributesReact Js 有条件地应用类属性
【发布时间】:2015-08-12 12:46:20
【问题描述】:

我想根据从父组件传入的内容有条件地显示和隐藏此按钮组,如下所示:

<TopicNav showBulkActions={this.__hasMultipleSelected} />

....

__hasMultipleSelected: function() {
  return false; //return true or false depending on data
}

....

var TopicNav = React.createClass({
render: function() {
return (
    <div className="row">
        <div className="col-lg-6">
            <div className="btn-group pull-right {this.props.showBulkActions ? 'show' : 'hidden'}">
                <button type="button" className="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
                  Bulk Actions <span className="caret"></span>
                </button>
                <ul className="dropdown-menu" role="menu">
                  <li><a href="#">Merge into New Session</a></li>
                  <li><a href="#">Add to Existing Session</a></li>
                  <li className="divider"></li>
                  <li><a href="#">Delete</a></li>
                </ul>
            </div>
        </div>
    </div>
    );
  }
});

但是,{this.props.showBulkActions 没有发生任何事情? “显示”:“隐藏”}。我在这里做错了吗?

【问题讨论】:

  • 您可能还希望考虑react-bootstrap,因为这会将一些类内容抽象为组件属性,从而使您尝试做的事情变得更容易。

标签: javascript css twitter-bootstrap-3 reactjs class-attributes


【解决方案1】:

花括号在字符串内部,因此它被视为字符串。他们需要在外面,所以这应该有效:

<div className={"btn-group pull-right " + (this.props.showBulkActions ? 'show' : 'hidden')}>

注意“pull-right”后面的空格。您不想意外地提供类“pull-rightshow”而不是“pull-right show”。括号也需要在那里。

【讨论】:

  • 谢谢!我不得不稍微修改它,因为由于某种原因它根本没有输出 btn-group pull-right。只显示或隐藏。
  • 这在 classnames 可能不合适的某些情况下特别有用。如果您在您的render 函数中并且您有一个map,您可能只知道在渲染它时是否要添加一个类,所以这个答案对此非常有用。
  • 很好的选择,而不是在渲染或返回中使用一堆条件模板
  • @apexdodge 您必须进行哪些修改。我有同样的问题。
  • @RamY 一种方法是将所有类放在条件this.props.showBulkActions ? 'btn-group pull-right show' : 'btn-group pull-right hidden') 中。不优雅,但它有效。
【解决方案2】:

正如其他人评论的那样,classnames 实用程序是当前推荐的在 ReactJs 中处理条件 CSS 类名称的方法。

在您的情况下,解决方案将如下所示:

var btnGroupClasses = classNames(
  'btn-group',
  'pull-right',
  {
    'show': this.props.showBulkActions,
    'hidden': !this.props.showBulkActions
  }
);

...

<div className={btnGroupClasses}>...</div>

附带说明,我建议您尽量避免同时使用showhidden 类,这样代码会更简单。很可能,您不需要为默认显示的内容设置类。

2021 附录:为了提高性能,您可以查看clsx 作为替代方案。

【讨论】:

  • 您能否详细说明 classNames 实用程序是“当前推荐的方法”?这是否包含在某处备受推崇的最佳实践文档中?或者只是目前关于 React 和 classNames 的口口相传?
  • @anied 在撰写本文时,React 官方文档中建议使用它:web.archive.org/web/20160602124910/http://facebook.github.io:80/…
  • latest documentation中还是有提到:“如果你经常发现自己写这样的代码,classnames包可以简化。
  • 从 2021 年开始,您可能想尝试使用 classnames 而不是 clsx
【解决方案3】:

如果您使用的是转译器(例如Babel 或 Traceur),您可以使用新的 ES6“template strings”。

这里是@spitfire109 的回答,经过相应修改:

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'shown' : 'hidden'}`}>

这种方法允许你做类似的事情,渲染s-is-showns-is-hidden

<div className={`s-${this.props.showBulkActions ? 'is-shown' : 'is-hidden'}`}>

【讨论】:

  • 小心第二种方法,尤其是在大型代码库中,因为它使类字符串不易被抓取。例如,如果有人在代码库中搜索s-is-showns-is-hidden,他们将找不到此代码。
【解决方案4】:

你可以在这里使用字符串字面量

const Angle = ({show}) => {

   const angle = `fa ${show ? 'fa-angle-down' : 'fa-angle-right'}`;

   return <i className={angle} />
}

【讨论】:

    【解决方案5】:

    例如,您可以简单地执行以下操作。

    let classNameDependsOnCondtion = i18n.language == 'en' ? "classname" : "";
    
    className={`flex flex-col lg:flex-row list-none ${classNameDependsOnCondtion }`}
    

    className={`flex flex-col lg:flex-row list-none ${i18n.language == 'en' ? "classname" : ""}`}
    

    【讨论】:

    • 如果您有条件地内联渲染单个 className 并且不希望在其中一个条件下出现类,您可以返回 nullundefined 而不是空字符串。示例:className={condition ? 'red' : null}className={condition ? 'red' : undefined} 最好保持标记干净,而不是让元素看起来像 &lt;div class&gt; 或 `
    • @AnthonyAvila true,最好使用类名npmjs.com/package/classnames 以避免打印额外的空格。
    【解决方案6】:

    如果您只需要一个可选的类名:

    <div className={"btn-group pull-right " + (this.props.showBulkActions ? "show" : "")}>
    

    【讨论】:

    • 这将在条件失败时附加false 类。
    • 三元中的""使用null,如果没有,则在元素中设置class属性,不使用null更好
    【解决方案7】:

    利用@spitfire109 的好答案,可以做这样的事情:

    rootClassNames() {
      let names = ['my-default-class'];
      if (this.props.disabled) names.push('text-muted', 'other-class');
    
      return names.join(' ');
    }
    

    然后在渲染函数内:

    <div className={this.rootClassNames()}></div>
    

    保持 jsx 简短

    【讨论】:

      【解决方案8】:

      或者使用 npm classnames。它非常简单实用,尤其是对于构建类列表

      【讨论】:

        【解决方案9】:

        您可以使用 ES6 数组代替类名。 答案基于 Axel Rauschmayer 博士的文章:Conditionally adding entries inside Array and object literals

        <div className={[
                         "classAlwaysPresent", 
                         ...Array.from(condition && ["classIfTrue"])
                        ].join(" ")} />
        

        【讨论】:

        • 请扩展一下,条件是什么?
        • const 条件 = (1 === 1);
        【解决方案10】:

        替换:

        <div className="btn-group pull-right {this.props.showBulkActions ? 'show' : 'hidden'}">`
        

        与:

        <div className={`btn-group pull-right ${this.props.showBulkActions ? 'show' : 'hidden'}`}
        

        【讨论】:

          【解决方案11】:

          2019:

          React 提供了很多实用程序。但是你不需要任何npm 包。只需在某处创建函数classnames 并在需要时调用它;

          function classnames(obj){
            return Object.entries(obj).filter( e => e[1] ).map( e=>e[0] ).join(' ');
          }
          

          function classnames(obj){
           return Object.entries(obj).map( ([k,v]) => v?k:'' ).join(' ');
          }
          

          例子

            stateClass= {
              foo:true,
              bar:false,
              pony:2
            }
            classnames(stateClass) // return 'foo pony'
          
          
          
           <div className="foo bar {classnames(stateClass)}"> some content </div>
          

          只为灵感

          声明辅助元素并使用toggle方法

          (DOMToken​List)classList.toggle(class,condition)

          示例:

          const classes = document.createElement('span').classList; 
          
          function classstate(obj){
            for( let n in obj) classes.toggle(n,obj[n]);
           return classes; 
          }
          
          

          【讨论】:

            【解决方案12】:

            更优雅的解决方案,更利于维护和可读性:

            const classNames = ['js-btn-connect'];
            
            if (isSelected) { classNames.push('is-selected'); }
            
            <Element className={classNames.join(' ')}/>
            

            【讨论】:

              【解决方案13】:

              你可以用这个:

              <div className={"btn-group pull-right" + (this.props.showBulkActions ? ' show' : ' hidden')}>
              

              【讨论】:

                【解决方案14】:

                当您要附加多个类时,这很有用。您可以使用空格加入数组中的所有类。

                const visibility = this.props.showBulkActions ? "show" : ""
                <div className={["btn-group pull-right", visibility].join(' ')}>
                

                【讨论】:

                  【解决方案15】:
                  <div className={['foo', condition && 'bar'].filter(Boolean).join(' ')} />
                  

                  .filter(Boolean) 从数组中删除“假”值。由于类名必须是 strings,除此之外的任何内容都不会包含在 new 过滤数组中。

                  console.log(  ['foo', true  && 'bar'].filter(Boolean).join(' ')  )
                  console.log(  ['foo', false && 'bar'].filter(Boolean).join(' ')  )

                  以上写成函数:

                  const cx = (...list) => list.filter(Boolean).join(' ')
                  
                  // usage:
                  <div className={cx('foo', condition && 'bar')} />
                  

                  var cx = (...list) => list.filter(Boolean).join(' ')
                  console.log(  cx('foo', 1 && 'bar', 1 && 'baz')  )
                  console.log(  cx('foo', 0 && 'bar', 1 && 'baz')  )
                  console.log(  cx('foo', 0 && 'bar', 0 && 'baz')  )

                  【讨论】:

                    【解决方案16】:

                    这对你有用

                    var TopicNav = React.createClass({
                    render: function() {
                    
                    let _myClasses = `btn-group pull-right {this.props.showBulkActions?'show':'hidden'}`;
                    
                    return (
                                ...
                                <div className={_myClasses}>
                                   ...
                                </div>
                        );
                      }
                    });
                    

                    【讨论】:

                      【解决方案17】:

                      参考@split fire的答案,我们可以用模板字面量来更新,更具可读性,供参考Checkout javascript template literal

                      <div className={`btn-group pull-right ${this.props.showBulkActions ? 'show' : 'hidden'}`}>
                      

                      【讨论】:

                        【解决方案18】:

                        您可以使用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', null, undefined, 3, ['class3', 'class4'], { 
                            class5 : function() { return false; },
                            class6 : function() { return true; }
                        });
                        
                        <div className={getClassNames('show', {class1: true, class2 : false})} /> // "show class1"
                        

                        【讨论】:

                          【解决方案19】:

                          根据this.props.showBulkActions 的值,您可以动态切换类,如下所示。

                          <div ...{...this.props.showBulkActions 
                          ? { className: 'btn-group pull-right show' } 
                          : { className: 'btn-group pull-right hidden' }}>
                          

                          【讨论】:

                            【解决方案20】:

                            我想补充一点,你也可以使用一个变量内容作为类的一部分

                            <img src={src} alt="Avatar" className={"img-" + messages[key].sender} />
                            

                            上下文是机器人和用户之间的聊天,样式根据发送者而变化,这是浏览器的结果:

                            <img src="http://imageurl" alt="Avatar" class="img-bot">
                            

                            【讨论】:

                              【解决方案21】:

                              根据参数(如果存在)返回正确类的函数

                                getClass(param){
                                  let podClass = 'classA'
                                  switch(param.toLowerCase()){
                                      case 'B':
                                          podClass  = 'classB'
                                          break;
                                      case 'C':
                                          podClass  = 'classC'
                                          break;
                                  }
                                  return podClass
                              }
                              

                              现在只需从要应用相应类的 div 中调用此函数。

                               <div className={anyOtherClass + this.getClass(param)}
                              

                              我成功地使用此逻辑将正确的颜色应用于我的引导表行。

                              【讨论】:

                                猜你喜欢
                                相关资源
                                最近更新 更多
                                热门标签