在React中处理条件样式的正确方法


102

我现在正在做一些React,我想知道是否有一种“正确的”方式来进行条件样式设计。在本教程中,他们使用

style={{
  textDecoration: completed ? 'line-through' : 'none'
}}

我不想使用内联样式,因此我想使用一个类来控制条件样式。一个人将如何以React的思维方式来实现这一目标?还是应该只使用这种内联样式方式?


1
我想你可能有reduxreact混淆。Redux与样式无关。
rossipedia '16

3
我认为您偏爱文档,但是对于标记互换兼容性不重要的应用程序则过于热情。实际上,一些主要的Web应用程序摆脱了类的限制,仅使用了内联样式,这比5个应用规则中的哪一个使文本为粗体更容易预测和推理。当属性是动态的时,您不会像处理重复文档那样节省很多带宽。应用程序的语义(视图源标记)也不那么重要……
dandavis

@rossipedia啊是的,谢谢,感到困惑,在考虑这个时正在查看redux教程,谢谢!
davidhtien

如果您不确定由于级联而导致的文本装饰的值是什么,并且仅当complete为true时才想应用换行,则必须构建一个样式对象。这样,当它是另一个值时,您不会将它意外地设置为none。const style = {} if(complete){style ['textDecoration'] ='line-through'}
爱德华

Answers:


80

如果您更喜欢使用类名,请务必使用类名。

className={completed ? 'text-strike' : null}

您可能还会发现类名称很有用。有了它,您的代码将如下所示:

className={classNames({ 'text-strike': completed })}

没有“正确”的方法来进行条件样式设计。做最适合您的事情。就我自己而言,我更喜欢避免内联样式,并以上述方式使用类。

POSTSCRIPT [06-AUG-2019]

尽管React在样式方面毫无疑问,但这些天我还是会推荐CSS-in-JS解决方案。即风格成分情感。如果您不熟悉React,请坚持使用CSS类或内联样式。但是一旦您对React感到满意,我建议您采用这些库之一。我在每个项目中都使用它们。


嘿,如果您决定使用className作为条件样式方法。没有classNames lib。我建议您使用undefined而不是null。的className属性作为输入类型的字符串或未定义-型(String |未定义) - ⚡️
0XX

4
@JadRizk更好的方法是,如果您没有有效的值将className设置为完全不设置。const attrs = completed?{className:'text-strike'}:{}然后<li {...attrs}>text to maybe strike</li>(扩展运算符)。这样,您根本就不会设置className,除非您要分配一个好的值。这是设置某些内联样式的重要方法,在这些样式中您不知道当前值是什么(因为它可能由CSS设置在您无法控制的文件中)。
LinuxDisciple

@LinuxDisciple如果所有字段的评估结果均为false,则classnames仅返回一个空字符串。这不会受到任何CSS的影响。
大卫·沃尔什

@ DavidL.Walsh 21小时前,我认为JadRizk的解决方案是在之间做出错误选择,null并且undefined仍然会导致classhtml中没有值属性(即,<p class></p>而不是<p></p>),因此我提供了一种完全避免设置的方法className。碰巧的是,我对JadRizk的解决方案是错误的。对于上述问题,我相信您采用JadRizk改进的解决方案是最好的。我的语法可以有条件地设置prop及其值的任意列表,但是仅设置类名就太过分了。
LinuxDisciple

112
 <div style={{ visibility: this.state.driverDetails.firstName != undefined? 'visible': 'hidden'}}></div>

检出上面的代码。这样就可以了。


4
正是在寻找这样的东西。有条件的内联样式,谢谢。
Souvik Ghosh '18年

<div style = {{可见性:this.state.driverDetails.firstName!==未定义?'visible':'hidden'}}> </ div>。==中的小错字。
vinayak shahdeo

39

如果您需要有条件地应用内联样式(全部应用或不应用任何样式),则该符号也可以使用:

style={ someCondition ? { textAlign:'center', paddingTop: '50%'} : {}}

如果未满足“ someCondition”,则您传递空对象。


2
这种模式是否会造成不必要的差异?我对DOM差异的理解是,style此处的支持总是会更改,因为在Javascript中,{} != {} 如果我对差异正确,那么最好使用“ undefined”代替“ {}
Dawson B

1
好注意 我对此不确定。
弗拉多

8

首先,就样式而言,我同意您的看法-我也(并且也)有条件地应用类而不是内联样式。但是您可以使用相同的技术:

<div className={{completed ? "completed" : ""}}></div>

对于更复杂的状态集,请累积一组类并应用它们:

var classes = [];

if (completed) classes.push("completed");
if (foo) classes.push("foo");
if (someComplicatedCondition) classes.push("bar");

return <div className={{classes.join(" ")}}></div>;

8

代替这个:

style={{
  textDecoration: completed ? 'line-through' : 'none'
}}

您可以使用短路尝试以下方法:

style={{
  textDecoration: completed && 'line-through'
}}

https://codeburst.io/javascript-short-circuit-conditionals-bbc13ac3e9eb

链接中的关键信息:

短路意味着在JavaScript中,当我们评估一个AND表达式(&&)时,如果第一个操作数为false,则JavaScript将短路,甚至不查看第二个操作数。

值得注意的是,如果第一个操作数为false,则此操作将返回false,因此可能必须考虑这将如何影响您的样式。

其他解决方案可能是最佳实践,但认为值得分享。


4

另一种方式,使用内联样式和传播运算符

style={{
  ...completed ? { textDecoration: completed } : {}
}}

在某些情况下,您想根据条件同时添加一堆属性,这种方法很有用。


1
如果您不想更改默认样式

2

我在尝试回答同一问题时遇到了这个问题。McCrohan的类数组和联接方法是可靠的。

根据我的经验,我一直在处理许多遗留的ruby代码,这些代码已被转换为React,在我们构建组件时,我发现自己接触了现有的CSS类和内联样式。

组件内的示例代码段:

// if failed, progress bar is red, otherwise green 
<div
    className={`progress-bar ${failed ? failed' : ''}`}
    style={{ width: this.getPercentage() }} 
/>

再次,我发现自己接触了遗留的CSS代码,将其与组件“打包”在一起并继续前进。

因此,我真的觉得什么是“最好的”还有些悬而未决,因为标签会因您的项目而有很大差异。


您不应该将classNames与style属性结合使用,这有点混乱
SebastianVoráč19年

0

处理样式的最佳方法是使用带有css属性集的类。

例:

<Component className={this.getColor()} />

getColor() {
    let class = "badge m2";
    class += this.state.count===0 ? "warning" : danger;
    return class;
}

0

您可以使用这样的东西。

render () {
    var btnClass = 'btn';
    if (this.state.isPressed) btnClass += ' btn-pressed';
    else if (this.state.isHovered) btnClass += ' btn-over';
    return <button className={btnClass}>{this.props.label}</button>;
  }

否则,您可以使用classnames NPM包使动态和条件className道具更易于使用(尤其是比条件字符串操作更简单)。

classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'
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.