React.js内联样式最佳实践

时间:2014-11-12 08:16:24

标签: css reactjs inline-styles react-jsx

我知道您可以在React类中指定样式,如下所示:

var MyDiv = React.createClass({
  render: function() {
    var style = {
      color: 'white',
      fontSize: 200
    };

    return <div style={style}> Have a good and productive day! </div>;
  }
});

我是否应该以这种方式做所有样式,并且我的CSS文件中没有指定任何样式?

或者我应该完全避免使用内联样式吗?

做两件事似乎很奇怪和混乱 - 在调整样式时需要检查两个地方。

20 个答案:

答案 0 :(得分:422)

还没有很多“最佳实践”。对于React组件,我们这些使用内联样式的人仍然在进行实验。

有许多方法变化很大:React inline-style lib comparison chart

全有或全无?

我们所说的“风格”实际上包含了很多概念:

  • 布局 - 元素/组件与其他人的关系
  • 外观 - 元素/组件的特征
  • 行为和状态 - 元素/组件在给定状态下的外观

以州样式

开头

React已经在管理组件的状态,这使得状态和行为的样式非常适合与组件逻辑进行共置。

不是构建要使用条件状态类进行渲染的组件,而是考虑直接添加状态样式:

// Typical component with state-classes
<li 
 className={classnames({ 'todo-list__item': true, 'is-complete': item.complete })} />


// Using inline-styles for state
<li className='todo-list__item'
 style={(item.complete) ? styles.complete : {}} />

请注意,我们正在使用一个类来设置外观的样式,但不再使用任何.is-前缀类来处理状态和行为

我们可以使用Object.assign(ES6)或_.extend(下划线/ lodash)来添加对多个状态的支持:

// Supporting multiple-states with inline-styles
<li 'todo-list__item'
 style={Object.assign({}, item.complete && styles.complete, item.due && styles.due )}>

自定义和可重用性

现在我们正在使用Object.assign,使用不同的样式重新组合我们的组件变得非常简单。如果我们想覆盖默认样式,我们可以在带有props的调用站点上执行此操作,如:<TodoItem dueStyle={ fontWeight: "bold" } />。像这样实现:

<li 'todo-list__item'
 style={Object.assign({},
         item.due && styles.due,
         item.due && this.props.dueStyles)}>

布局

就个人而言,我没有看到内联布局样式的令人信服的理由。有很多很棒的CSS布局系统。我只想用一个。

也就是说,不要直接向组件添加布局样式。使用布局组件包装组件。这是一个例子。

// This couples your component to the layout system
// It reduces the reusability of your component
<UserBadge
 className="col-xs-12 col-sm-6 col-md-8"
 firstName="Michael"
 lastName="Chan" />

// This is much easier to maintain and change
<div class="col-xs-12 col-sm-6 col-md-8">
  <UserBadge
   firstName="Michael"
   lastName="Chan" />
</div>

对于布局支持,我经常尝试将组件设计为100% widthheight

外观

这是“内联式”辩论中最具争议的领域。最终,它取决于您的设计组件以及使用JavaScript的团队的舒适度。

有一件事是肯定的,你需要图书馆的协助。浏览器状态(:hover:focus)和媒体查询在原始React中很痛苦。

我喜欢Radium,因为这些硬件的语法是为SASS的模型设计的。

代码组织

通常,您会在模块外部看到样式对象。对于todo-list组件,它可能看起来像这样:

var styles = {
  root: {
    display: "block"
  },
  item: {
    color: "black"

    complete: {
      textDecoration: "line-through"
    },

    due: {
      color: "red"
    }
  },
}

getter函数

在模板中添加一堆样式逻辑可能会有点混乱(如上所示)。我喜欢创建getter函数来计算样式:

React.createClass({
  getStyles: function () {
    return Object.assign(
      {},
      item.props.complete && styles.complete,
      item.props.due && styles.due,
      item.props.due && this.props.dueStyles
    );
  },

  render: function () {
    return <li style={this.getStyles()}>{this.props.item}</li>
  }
});

进一步观看

今年早些时候,我在React Europe更详细地讨论了所有这些问题:Inline Styles and when it's best to 'just use CSS'

我很乐意帮助您沿途创造新的发现:)打我 - > @chantastic

答案 1 :(得分:98)

React中的style属性期望值为对象,即键值对。

style = {}会在其中包含另一个对象{float:'right'},以使其有效。

<span style={{float:'right'}}>{'Download Audit'}</span>

希望这能解决问题

答案 2 :(得分:46)

我在React组件中广泛使用内联样式。我发现在组件中共置样式更加清晰,因为它总是清楚组件所具有和不具有的样式。此外,拥有Javascript的全部功能确实简化了更复杂的样式需求。

我一开始并不相信,但在涉及它几个月后,我已完全转换,并且正在将我的所有CSS转换为内联或其他JS驱动的css方法。

Facebook员工和React撰稿人“vjeux”的演示也非常有用 - https://speakerdeck.com/vjeux/react-css-in-js

答案 3 :(得分:22)

style属性的主要用途是动态的,基于状态的样式。例如,您可以根据某个状态在进度条上设置宽度样式,或者根据其他状态设置位置或可见性。

JS中的样式强加了应用程序无法为可重用组件提供自定义样式的限制。在上述情况下,这是完全可以接受的,但是当您更改可见特征(尤其是颜色)时则不是这样。

答案 4 :(得分:17)

James K Nelson在他的信"Why You Shouldn’t Style React Components With JavaScript"中指出,实际上并没有必要使用内联样式及其缺点。他的陈述是,使用less / scss的旧无聊的CSS是最好的解决方案。他的论文部分支持css:

  • 外部可扩展
  • leverable(内联样式超越一切)
  • 设计者友好

答案 5 :(得分:8)

我所做的是为每个可重用组件提供一个唯一的自定义元素名称,然后为该组件创建一个css文件,特别是该组件的所有样式选项(并且仅针对该组件)。

var MyDiv = React.createClass({
  render: function() {
    return <custom-component style={style}> Have a good and productive day! </custom-component>;
  }
});

在文件&#39; custom-component.css&#39;中,每个条目都将以自定义组件标记开头:

custom-component { 
   display: block; /* have it work as a div */
   color: 'white'; 
   fontSize: 200; 
} 
custom-component h1 { 
  font-size: 1.4em; 
}

这意味着你没有放弃分离关注的关键概念。查看与风格。如果您共享您的组件,则其他主题更容易与其网页的其余部分匹配。

答案 6 :(得分:5)

这真的取决于你的应用程序是如何,如果你想使用像 webpack 这样的捆绑包,并在构建中捆绑CSS和JS,以及你想如何管理你的应用程序流!在一天结束时,取决于你的情况,你可以做出决定!

我在大项目中组织文件的偏好是分离 CSS和JS 文件,它可以更容易共享,UI用户更容易通过CSS文件,也更简洁的文件组织整个申请!

始终以这种方式思考,确保在开发阶段,一切都在应有的位置,正确命名并让其他开发人员轻松找到东西......

我个人混合他们取决于我的需要,例如...... 尝试使用外部css,但如果需要,React也会接受样式,你需要将它作为具有键值的对象传递,如下所示:

import React from 'react';

const App = props => {
  return (
    <div className="app" style={{background: 'red', color: 'white'}}>  /*<<<<look at style here*/
      Hello World...
    </div>
  )
}

export default App;

答案 7 :(得分:3)

对于某些组件,使用内联样式更容易。此外,我发现它更容易,更简洁(因为我使用Javascript而不是CSS)来动画组件样式。

对于独立组件,我使用&#39; Spread Operator&#39;或者&#39; ...&#39;。对我而言,它清晰,美观,并且在狭小的空间中工作。这是一个小小的加载动画,我展示了它的好处:

<div style={{...this.styles.container, ...this.state.opacity}}>
    <div style={{...this.state.colors[0], ...this.styles.block}}/>
    <div style={{...this.state.colors[1], ...this.styles.block}}/>
    <div style={{...this.state.colors[2], ...this.styles.block}}/>
    <div style={{...this.state.colors[7], ...this.styles.block}}/>
    <div style={{...this.styles.block}}/>
    <div style={{...this.state.colors[3], ...this.styles.block}}/>
    <div style={{...this.state.colors[6], ...this.styles.block}}/>
    <div style={{...this.state.colors[5], ...this.styles.block}}/>
    <div style={{...this.state.colors[4], ...this.styles.block}}/>
  </div>

    this.styles = {
  container: {
    'display': 'flex',
    'flexDirection': 'row',
    'justifyContent': 'center',
    'alignItems': 'center',
    'flexWrap': 'wrap',
    'width': 21,
    'height': 21,
    'borderRadius': '50%'
  },
  block: {
    'width': 7,
    'height': 7,
    'borderRadius': '50%',
  }
}
this.state = {
  colors: [
    { backgroundColor: 'red'},
    { backgroundColor: 'blue'},
    { backgroundColor: 'yellow'},
    { backgroundColor: 'green'},
    { backgroundColor: 'white'},
    { backgroundColor: 'white'},
    { backgroundColor: 'white'},
    { backgroundColor: 'white'},
    { backgroundColor: 'white'},
  ],
  opacity: {
    'opacity': 0
  }
}

然后,在componentWillMount()中,我设置了一个像这样的间隔......

this.interval = setInterval(() => {
  let colors = this.state.colors;
  let opacity = this.state.opacity;

  if(this.props.reverse) {
    let color = colors[colors.length-1];
    colors.pop();
    colors.unshift(color)
  } else {
    let color = colors[0];
    colors.shift();
    colors.push(color);
  }

  opacity['opacity'] < 1 ? opacity['opacity']+=0.06 : null;

  this.setState({colors, opacity});
}, this.speed);

答案 8 :(得分:3)

JSX中的样式与HTML中的样式非常相似。

HTML案例:

  

div style =“ background-color:red; color:white”

JSX案例:

  

div style = {{backgroundColor:'red',color:'white'}}

答案 9 :(得分:3)

根据您的配置,内联样式可以为您提供热重新加载。每次样式更改时都会立即重新呈现网页。这有助于我更快地开发组件。话虽如此,我确信您可以为CSS + SCSS设置热重载环境。

答案 10 :(得分:3)

我通常有与每个React组件关联的scss文件。但是,我不明白为什么你不会用逻辑封装组件并查看它。我的意思是,你有与Web组件类似的东西。

答案 11 :(得分:2)

您也可以使用StrCSS,它可以创建隔离的类名等等!示例代码看起来像。您可以(可选)从Visual Studio Marketplace安装VSCode扩展,以获得语法突出显示支持!

来源:https://github.com/jeffreylanters/strcss

import { Sheet } from "strcss";
import React, { Component } from "react";

const sheet = new Sheet(`
  map button
    color green
    color red !ios
    fontSize 16
  on hover
    opacity .5
  at mobile
    fontSize 10
`);

export class User extends Component {
  render() {
    return <div className={sheet.map.button}>
      {"Look mom, I'm green!
      Unless you're on iOS..."}
    </div>;
  }
}

答案 12 :(得分:2)

您可以使用内联样式,但是如果在所有样式中都使用它们,则会受到一些限制,一些已知的限制是您不能使用 CSS伪选择器媒体查询

您可以使用 Radium https://github.com/FormidableLabs/radium解决此问题,但我仍然认为该项目的发展会变得麻烦。

我建议使用 CSS模块 https://github.com/css-modules/css-modules

使用 CSS模块,您将可以自由地在CSS文件中编写CSS,而不必担心命名冲突,CSS模块会予以注意。

此方法的优点是,它为您提供了特定组件的样式功能。这将为下一开发人员创建更多可维护的代码和可读的项目体系结构。

答案 13 :(得分:2)

内联样式的问题是内容安全策略(CSP)变得越来越普遍,不允许它。因此,我建议完全避免使用内联样式。

<强>更新 为了进一步说明,CSP是服务器发送的HTTP标头,用于限制页面上可以显示的内容。它只是一个进一步的缓解,可以应用于服务器,以阻止攻击者做一些顽皮的事情,如果开发人员对网站编码不好。

大多数这些限制的目的是阻止XSS(跨站点脚本)攻击。 XSS是攻击者在您的页面上找到一种方法来包含他自己的javascript(例如,如果我使用我的用户名bob<SCRIPT>alert("hello")</SCRIPT>然后发表评论,并且您访问该页面,则不应该显示警告)。开发人员应该拒绝让用户向网站添加这样的内容,但是如果他们犯了错误,那么如果CSP找到任何script>标签,CSP就会阻止加载页面。

CSP只是为开发人员提供额外级别的保护,以确保他们犯了错误,攻击者不会对该网站的访问者造成问题。

所有这些都是XSS,但是如果攻击者不能包含<script>标记但可以包含<style>标记或在标记上包含style=参数怎么办?然后他可能会以这样的方式改变网站的外观,以至于你被欺骗点击错误的按钮或其他一些问题。这不是一个值得关注的问题,但仍有一些问题需要避免,CSP会为您做到这一点。

为CSP测试网站的一个很好的资源是https://securityheaders.io/

您可以在http://www.html5rocks.com/en/tutorials/security/content-security-policy/

了解有关CSP的更多信息

答案 14 :(得分:1)

这是 JSX 语法中基于布尔的样式:

style={{display: this.state.isShowing ? "inherit" : "none"}}

答案 15 :(得分:1)

与在css文件中编写样式相比, React的样式属性具有以下优点

  1. 使用javascript工具作为编程语言的能力可以控制元素的样式。这包括嵌入变量,使用条件以及将样式传递给子组件。
  2. “组成部分”方法。为组件编写的HTML,JS和CSS代码不再分开。组件的代码被合并,并写在一个地方。

但是, React的样式属性有一些缺点-您不能

  1. 不能使用媒体查询
  2. 不能使用伪选择器,
  3. 与CSS类相比,效率更低。

使用JS中的CSS,您可以获得样式标签的所有优点,而没有那些缺点。到今天为止,js库中有一些受欢迎且受良好支持的CSS,包括:Emotion,Styled-Components和Radium。这些库对CSS来说就像React对HTML一样。它们允许您编写CSS并在JS代码中控制CSS。

让我们比较一下我们的代码将如何样式化简单元素。我们将设置“ hello world” div的样式,使其在桌面上显示较大,而在移动设备上显示较小。

使用样式属性

return (
   <div style={{fontSize:24}} className="hello-world">
      Hello world
   </div>
)

由于无法在style标签中进行媒体查询,因此我们必须在元素中添加className并添加CSS规则。

@media screen and (max-width: 700px){
   .hello-world {
      font-size: 16px; 
   }
}

使用Emotion的10个CSS标签

return (
   <div
      css={{
         fontSize: 24, 
         [CSS_CONSTS.MOBILE_MAX_MEDIA_QUERY]:{
            fontSize: 16 
         }
      }
   >
      Hello world
   </div>
)

Emotion还支持模板字符串以及样式化的组件。因此,如果您愿意,可以写:

return (
   <Box>
      Hello world
   </Box>
)

const Box = styled.div`
   font-size: 24px; 
   ${CSS_CONSTS.MOBILE_MAX_MEDIA_QUERY}{
      font-size: 16px; 
   }
`

引擎盖后面的“ JS中的Css”使用css类。情感是专门考虑性能而构建的,并使用缓存。与React样式属性相比,JS中的Css将提供更好的性能。

最佳做法

以下是我推荐的一些最佳做法:

  1. 如果要内联或在JS中设置元素的样式,请使用css-in-js库,不要使用样式属性。
  

我应该以此方式进行所有样式设置,并且在CSS文件中完全没有指定样式吗?

  1. 如果使用css-in-js解决方案,则无需在Css文件中编写样式。用JS编写CSS更为出色,因为您可以使用JS提供的所有编程语言工具。
  

我应该完全避免使用内联样式吗?

  1. 在JS中构造样式代码与在一般情况下构造代码非常相似。例如:
    • 识别重复的样式,并将其写在一个地方。在Emotion中,有两种方法可以做到这一点:
// option 1 - Write common styles in CONSTANT variables
// styles.js
export const COMMON_STYLES = {
   BUTTON: css`
      background-color: blue; 
      color: white; 
      :hover {
         background-color: dark-blue; 
      }
   `
}

// SomeButton.js
const SomeButton = (props) => {
   ...
   return (
      <button
         css={COMMON_STYLES.BUTTON}
         ...
      >
         Click Me
      </button>
   )
}

// Option 2 - Write your common styles in a dedicated component 

const Button = styled.button`
   background-color: blue; 
   color: white; 
   :hover {
      background-color: dark-blue; 
   }   
`

const SomeButton = (props) => {
   ...
   return (
      <Button ...> 
         Click me
      </Button>
   )
}

  • 反应编码模式由封装的组件组成-将控制组件的HTML和JS写在一个文件中。那就是您要设置该组件样式的CSS /样式代码所在的位置。

  • 如有必要,在组件中添加样式道具。这样,您可以重用子组件中编写的代码和样式,并由父组件根据您的特定需求对其进行自定义。

const Button = styled.button([COMMON_STYLES.BUTTON, props=>props.stl])

const SmallButton = (props)=>(
   <Button 
      ...
      stl={css`font-size: 12px`}
   >
      Click me if you can see me
   </Button>
)

const BigButton = (props) => (
   <Button
      ...
      stl={css`font-size: 30px;`}
   >
      Click me
   </Button>
)

答案 16 :(得分:1)

2020更新:最佳做法是使用一个库,该库已经为您完成了艰苦的工作,并且如最初接受的答案所指出的那样,当您进行切换时不会杀死您的团队在this视频中显示(仍然有用)。也只是为了了解趋势this is a very helpful chart。在对此进行了自己的研究之后,我选择将Emotion用于我的新项目,事实证明它非常灵活且可扩展。

鉴于2015年获得最高评价的答案推荐了Radium,现在它已降为维护模式。因此,添加替代列表似乎是合理的。 post停产的Radium建议使用一些库。每个链接的站点都有易于使用的示例,因此我将避免在此处复制和粘贴代码。

  • Emotionstyled-components的启发,在js中使用样式,可以与框架无关,但肯定会推广其React库。截至本帖子为止,情绪一直保持最新。
  • styled-components具有可比性,并提供许多与Emotion相同的功能。也积极地得到维护。 Emotion和样式组件均具有相似的语法。它是专门为与React组件一起使用而构建的。
  • JSS js中样式的另一种选择是框架无关的,尽管它确实有许多框架程序包,其中包括React-JSS。

答案 17 :(得分:0)

有时候,我们需要为组件中的某些元素设置样式,但是如果我们必须仅显示该组件中的某个元素,或者样式是如此之少,则可以使用React js中的内联样式来代替CSS类。 reactjs内联样式与HTML内联样式相同,只是属性名称略有不同

使用style = {{prop:“ value”}}}

在任何标签中编写样式
import React, { Component } from "react";
    import { Redirect } from "react-router";

    class InlineStyle extends Component {
      constructor(props) {
        super(props);
        this.state = {};
      }

      render() {
        return (
          <div>
            <div>
              <div
                style={{
                  color: "red",
                  fontSize: 40,
                  background: "green"
                }}// this is inline style in reactjs
              >

              </div>
            </div>
          </div>
        );
      }
    }
    export default InlineStyle;

答案 18 :(得分:0)

绝不建议使用任何内联CSS。我们在基于JSS的项目中使用了样式化组件。它通过在组件上添加动态类名称来保护CSS覆盖。您还可以根据传递的道具添加css值。

答案 19 :(得分:0)

我更喜欢使用样式组件。它为设计提供了更好的解决方案。

<property>
  <name>yarn.resourcemanager.principal</name>
  <value>yarn/master.ar.com@AR.COM</value>
</property>