ChatGPT解决这个技术问题 Extra ChatGPT

React.js 内联样式最佳实践 [关闭]

关闭。这个问题是基于意见的。它目前不接受答案。想改进这个问题?更新问题,以便可以通过编辑这篇文章用事实和引用来回答它。去年关闭。改进这个问题

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

const MyDiv = React.createClass({
  render: function() {
    const style = {
      color: 'white',
      fontSize: 200
    };
    
    return <div style={style}> Have a good and productive day! </div>;
  }
});

我是否应该以这种方式进行所有样式设置,并且在我的 CSS 文件中完全没有指定样式?

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

两者都做一点点似乎很奇怪和混乱——在调整样式时需要检查两个地方。

在构建可重用组件时,您可以使用 react-theme 来组织您的内联样式并使其易于自定义。它的工作原理类似于 ThemeManager in material-ui
考虑使用 github.com/css-modules/css-modulesgithub.com/gajus/react-css-modules 是一个 React 实现(我是它的作者)。 CSS 模块和 React CSS 模块会自动将您的组件类名称映射到在文档范围内分配了唯一名称的 CSS 模块。
我在编写媒体查询时使用 CSS。我还使用来自基本 CSS 库(如 bootstrap)的类。
通常不推荐使用 style 属性作为元素样式的主要方式。 (reactjs.org/docs/dom-elements.html#style)
截至今天,我建议使用 css-in-js 解决方案。它具有 style 属性的所有优点,没有缺点。我写了一个答案stackoverflow.com/questions/26882177/…

s
sleske

目前还没有很多“最佳实践”。我们这些对 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 : {}} />

请注意,我们使用一个类来设置 appearance 样式,但不再使用任何以 .is- 为前缀的类来表示 state and behavior

我们可以使用 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 函数来计算样式:

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


伟大的阅读。 @chantastic 也非常感谢您的this relevant talk。 #公认
“用布局组件包装你的组件”:很明显,但正是我需要的。
@chantastic 很好的答案。一年过去了,这一切还是真的吗?只是真正进入 React 和内联样式的想法,只是想知道自从您发布此答案以来是否发生了任何变化。
@alexrussell 谢谢!我认为这里的答案仍然很好。改变的一个方面是 Aphrodite 似乎是社区首选的 inline-stiles 库(超过 Radium)——尽管这实际上是个人喜好问题。
@alexrussell 哎呀。不小心提前提交了。我现在使用这种组件技术来设置我的组件的样式。这个想法很简单。您创建的组件只关心样式的应用并使用这些组件而不是 divspana 等。无论您使用哪个库,它都有助于保持样式隔离。 reactpatterns.com/#Style 组件
R
Rafa Viotti

React 中的 style 属性期望值是一个对象,即键值对。

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

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

希望这能解决问题


那么如果我想在 JS 文件中使用 css 类,如何使用媒体查询
@PardeepJain 一种方法是使用 Emotion 如果您对 meet.js summit 2018 感兴趣,这里有完整的讲座
这种方法的一个缺点是内联定义样式每次都会创建一个新对象。这会在 style 属性中创建一个差异,这可能会导致性能问题。至少,在 render 之外定义一个像这样的常量样式。希望这可以帮助!
我多么希望每个答案都能如此简单直观地学习。
K
Kyle Mathews

我在我的 React 组件中广泛使用内联样式。我发现在组件中并置样式更加清晰,因为组件具有和不具有哪些样式总是很清楚。再加上手头拥有 Javascript 的全部功能,确实简化了更复杂的样式需求。

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

Facebook 员工和 React 贡献者“vjeux”的演示文稿也非常有帮助 — https://speakerdeck.com/vjeux/react-css-in-js


我将如何使用内联样式制作响应式布局?您在这里没有媒体查询的选项。
你得到了 js 的力量,js 可以检测浏览器大小来动态构建样式。
无论如何,@g3mini 现在不推荐使用这种方法,因为有更强大的解决方案来设置 CSS Modulesstyled-components 等组件的样式。
js 中也有 css =) 不过我现在更喜欢使用 CSS 模块。
这里没有考虑的一件事是很容易在同一个 SASS 文件中查看父样式和子样式,而如果您需要查看不同组件中的规则,则可能必须打开和关闭很多文件。
B
Brigand

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

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


我们有一段时间的一个相关想法是能够使用 gulp 和 LESS 为 React 组件隔离特定的 CSS 规则。有点像为每个组件设置一个特定的类名,然后在组件文件中为该类添加特定的 CSS。这很有意义。
我经常使用“component-{app}-{componentName}”格式的类名。 “{app}”可以是应用程序的名称,也可以是应用程序独立组件的“通用”名称。例如 TodoList 的“component-foo-todo-list”和“component-common-light-switch-toggle”。对于打包的组件 {app} 将是 npm 名称。你指的是这个吗?
是的,命名约定是一回事,但主要是将隔离的 CSS 规则添加到同一个组件 js 文件中。
这不是真的。您可以明确地将自定义样式应用于反应组件。组件只需要将自己的样式对象与上面传递的对象合并,该对象可以来自应用程序数据。请参阅 speakerdeck.com/vjeux/react-css-in-js 的最后一张幻灯片,如下所述
当然,如果您的组件是单个元素,但考虑到 <div><a>foo <b>bar</b></a><table>...</table></div>,您如何从道具中设置样式?请记住,html 结构应保留为实现细节,否则您将失去许多组件提供的好处。
V
Vivek Mehta

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

HTML 案例:

div style="背景颜色:红色;颜色:白色"

JSX 案例:

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


从背景色到背景色!这就是我需要的!
填充呢?
A
Andhi Irawan

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

可外部扩展

可分割的(内联样式覆盖一切)

设计师友好


B
Ben Carp

TLDR - 在 js 解决方案中使用 css(例如 Emotion 或 Styled Components),享受最好的 css 和 js 所提供的

在 css 或 scss 文件中,很难管理动态样式。在内联样式标签中,您不能使用媒体查询或伪选择器。

在 JS 中使用 CSS,您可以享受两全其美。 JS 中的 Css 之于 CSS 就像 React 之于 HTML。它允许将您的 css 编写为 JS 代码中的对象或字符串,并享受 javascript 生态系统的强大功能和工具。

时至今日,在 js 库中有一些流行且支持良好的 CSS,包括 Emotion、Styled-Components 和 Radium。

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

使用样式属性

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

由于在样式标签中无法进行媒体查询,我们必须为元素添加一个类名并添加一个 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; 
   }
`

“CSS in JS”在幕后使用 CSS 类。

最佳实践

以下是我推荐的一些最佳实践:

在 JS 解决方案中使用 CSS 在 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>
   )
}

React 编码模式是封装组件 - 控制组件的 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>
)

A
Anupam Maurya

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

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

A
Andhi Irawan

我所做的是给我的每个可重用组件一个唯一的自定义元素名称,然后为该组件创建一个 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; 
}

这意味着您不会失去关注点分离的关键概念。视图与风格。如果您共享您的组件,其他人更容易为其设置主题以匹配其网页的其余部分。


我就是这样做的。唯一的缺点是它是两个文件而不是一个。我可以忍受这一点。
A
Alireza

这实际上取决于您的应用程序有多大,如果您想在构建中使用 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;

d
dakt

我通常将 scss 文件关联到每个 React 组件。但是,我看不出你为什么不用逻辑封装组件并查看它的原因。我的意思是,您对 Web 组件也有类似的情况。


G
Guy

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


S
Silicum Silium

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

来源: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>;
  }
}

S
Silicum Silium

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

您可以使用 Radium 来解决这个问题,但我觉得项目发展起来会变得很麻烦。

我建议使用 CSS modules

使用 CSS 模块,您将可以自由地在 CSS 文件中编写 CSS,并且不必担心命名冲突,它会由 CSS 模块处理。

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


V
VocoJax

对于某些组件,使用内联样式更容易。此外,我发现动画组件样式更容易和更简洁(因为我使用的是 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
  }
}

编辑 2019 年 11 月

在该行业(财富 500 强公司)工作,我不允许制作任何内联样式。在我们的团队中,我们认为内联样式不可读且不可维护。而且,在亲眼目睹了内联样式如何使支持应用程序完全无法忍受之后,我不得不同意。我完全不鼓励内联样式。


A
Andhi Irawan

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

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

大多数这些限制的目的是阻止 XSS(跨站点脚本)攻击。 XSS 是攻击者想办法在您的页面上包含他自己的 javascript 的地方(例如,如果我将用户名设为 bob<SCRIPT>alert("hello")</SCRIPT>,然后发表评论,并且您访问了该页面,它不应该显示警报)。开发人员应拒绝让用户向网站添加此类内容,但以防万一他们犯了错误,如果发现任何 script> 标记,CSP 会阻止页面加载。

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

所以这一切都是 XSS,但是如果攻击者不能包含 <script> 标签但可以包含 <style> 标签或在标签上包含 style= 参数怎么办?然后他可能会改变网站的外观,让您被诱骗点击错误的按钮或出现其他问题。这不是什么大问题,但仍然需要避免,CSP 会为您做到这一点。

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

您可以在 http://www.html5rocks.com/en/tutorials/security/content-security-policy/ 阅读有关 CSP 的更多信息


你能解释一下吗?
您具体指的是 unsafe-inline 政策。此策略允许将样式元素 <style> 限制为应用于元素样式属性的内联样式:<div style="">。由于上面的问题是指样式属性,因此完全避免内联样式似乎是个坏建议。此外,react 建议将所有 CSS 移至 JS:github.com/reactjs/react-future/blob/master/04%20-%20Layout/…
@potench 该链接真的很棒,可能值得自己回答
不幸的是,@eye_mew 和 @Sam-Rad - @potench 的回答不正确。 CSP unsafe-inline 禁用所有形式的内联样式,包括样式属性。您可以通过 JS 以编程方式在元素上使用样式 API(例如 elem.style.color = 'blue';),但您不能在元素上设置样式属性(就像 script-src 指令中的 'unsafe-inline' 不允许内联脚本标签一样,但也onclick 属性和朋友。)
Facebook 团队提供了有关如何在 React v15 github.com/facebook/react/issues/5878 中针对 CSP 应用样式的更多信息。值得一读
S
SamsonTheBrave

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

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

Emotion 受样式组件等“启发”,在 js 中使用样式并且可以与框架无关,但肯定会促进其 React 库。在这篇文章中,情绪一直保持最新。

styled-components 具有可比性,并提供许多与 Emotion 相同的功能。也在积极维护中。 Emotion 和 styled-components 都有相似的语法。它是专门为使用 React 组件而构建的。

JSS js 中样式的另一种选择,它与框架无关,尽管它确实有许多框架包,其中包括 React-JSS。


A
ABHIJEET KHIRE

有时我们需要为组件中的某些元素设置样式,但是如果我们必须只显示该组件或者样式太少,那么我们不使用 CSS 类,而是在 react js 中使用内联样式。 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;

您能否添加一些有关此代码如何以及为何提供对 OP 问题的答案的更多信息?谢谢!
S
Shivang Gupta

无论如何,从不推荐内联 CSS。我们在项目中使用了基于 JSS 的 styled-components。它通过在组件上添加动态类名来保护 css 覆盖。您还可以根据传递的道具添加 css 值。


S
Shadow

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

import React, { Component, Fragment } from 'react'
import styled from 'styled-components';

const StyledDiv = styled.div`
    display: block;
    margin-left: auto;
    margin-right: auto;
    font-size:200; // here we can set static
    color: ${props => props.color} // set dynamic color by props
`;

export default class RenderHtml extends Component {
    render() {
        return (
            <Fragment>
                <StyledDiv color={'white'}>
                    Have a good and productive day!
                </StyledDiv>
            </Fragment>
        )
    }
}