首页 文章

React.js内联样式最佳实践

提问于
浏览
400

我知道你可以在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文件中没有指定任何样式?

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

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

13 回答

  • 21

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

    style = {} 将在其中包含另一个对象 {float:'right'} 以使其工作 .

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

    希望这能解决问题

  • 0

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

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

    Facebook员工和React贡献者"vjeux"的这次演示也非常有用 - https://speakerdeck.com/vjeux/react-css-in-js

  • 2

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

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

  • 46

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

    • 外部可扩展

    • leverable(内联样式覆盖所有内容)

    • 设计师友好

  • 1

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

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

    全有或全无?

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

    • 布局 - 元素/组件与其他元素的关系

    • 外观 - 元素/组件的特征

    • 行为和状态 - 元素/组件在给定状态下的外观

    从状态样式开始

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

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

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

    请注意,我们使用类来设置 appearance 样式,但不再使用 .is- 的任何 .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

  • 16

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

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

    并在文件中'custom-component.css',每个条目都将以custom-component标签开头:

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

    这意味着你不会失去关注分离的关键概念 . 查看与风格 . 如果您共享组件,则其他主题更容易与其他网页匹配 .

  • 80

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

    我在大型项目中组织文件的偏好是分离 CSS and 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;
    
  • 6

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

  • 401

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

  • 2

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

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

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

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

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

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

    您可以在以下位置了解有关CSP的更多信息:http://www.html5rocks.com/en/tutorials/security/content-security-policy/

  • 1

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

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

    <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);
    
  • 3

    您也可以使用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>;
      }
    }
    
  • 1

    您可以使用内联样式,但如果您在所有样式中使用它们,则会有一些限制,一些已知的限制是您不能在那里使用 CSS pseudo selectorsmedia queries .

    您可以使用 Radium https://github.com/FormidableLabs/radium来解决这个问题,但我觉得项目越来越难以解决 .

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

    使用 CSS Modules 你可以自由地在CSS文件中编写CSS,而不必担心命名冲突,它将由CSS模块处理 .

    此方法的一个优点是它为您提供特定组件的样式功能 . 这将为下一个开发人员为您的项目创建更加可维护的代码和可读的项目架构 .

相关问题