发布于 2025-12-08 0 阅读
0

Styled Components,你不想缺少的 React 应用样式库

Styled Components,你不想缺少的 React 应用样式库

在Twitter上关注我,很高兴接受您对主题或改进的建议/Chris

本文涵盖了 styled-components 3.0 版本。自此之后,版本发生了一些变化。值得查看发行说明,了解主要变更,发行说明

注意,我知道这篇文章的 Markdown 渲染看起来有点不对劲。如果太困扰你,可以看看原文

在 React 中,有很多方法可以设置组件的样式。这可能是我最喜欢的方法,它在概念上与其他样式设置方法略有不同。

 样式组件方法的案例

当你开始设计 React 组件的样式时,你可以选择定义 CSS 类并将它们分配给每个元素,如下所示:

<div className="card">
  <div className="card-header">
    <h3>{card.header}</h3>
  </div>
  <div className="content">{card.content}</div>
</div>

上述做法确实没有什么问题,这是一种可行的方法,尽管有些人可能认为这需要重复输入很多次这个词className

你可能会说,我可以分别为卡片、卡片标题和卡片内容创建一个组件。是的,我们可以这么做。那么它可能看起来像这样:

<card header={card.header}>
  {card.content}
</card>

现在,这个例子可能有点简单,创建这样的组件可能很容易。而且,我们都知道在 React 中创建组件是多么容易。

所以你需要问问自己,我真正需要的是一个组件吗?我只是想添加一些 CSS 样式,然后随意命名 HTML 元素。如果你有这种想法,那么styled-components这个库或许适合你。

安装和设置 styled-components

我们可以通过 NPM 简单地安装 styled-components,如下所示:

yarn add styled-components
// OR
npm install — save styled-components

之后,我们就可以在我们的 React 项目中使用它了。

我们的第一次造型

此库的主页以按钮为例。您最终可能会在应用中创建用于不同用途的不同按钮。您可能有默认按钮、主按钮、禁用按钮等等。样式化组件库可让您将所有 CSS 集中管理。让我们首先导入它:

import styled from ‘styled-components’;

现在要使用它,我们需要使用双反引号`,如下所示:

const Button = styled.button``;

此时,我们还没有任何可以工作的东西,但它向您展示了语法。

正如我们上面看到的,我们调用

styled.nameOfElement`` 

为我们的元素定义样式。让我们给它添加一些样式:

const Button = styled.button`
  background: black;
  color: white;
  border-radius: 7px;
  padding: 20px;
  margin: 10px;
  font-size: 16px;
  :disabled {
    opacity: 0.4;
  }
  :hover {
    box-shadow: 0 0 10px yellow;
  }
`;

从上面的例子中我们可以看到,我们能够将普通的 CSS 属性与伪选择器(如:disabled和)结合使用:hover

如果我们想将 Button 用作 JSX 的一部分,我们可以简单地这样做,如下所示:

<div>
  <Button>
    press me
  </Button>
</div>

我们可以将我们的Button与我们想​​要的所有 HTML 或 JSX 混合在一起,并且可以像 HTML 元素一样对待它button,因为它就是一个,只是添加了一些 CSS 样式。

使用属性

styled-component库可以通过查找元素上指定属性的出现来有条件地应用样式。我们可以使用现有的属性,也可以自定义属性。

下面我们有一个定义按钮的示例。按钮与按钮primary的区别是什么?在应用程序中,我们有各种各样的按钮,通常有一个默认按钮,但也有一个主按钮,这是页面上最重要的按钮,通常用于执行诸如保存表单之类的操作。primarynormal

以不同的方式设置主按钮的样式是一种很常见的情况,因此我们可以看到这种按钮与普通按钮之间的区别,normal以便用户了解按下该按钮的重要性。

现在让我们展示如何设计这样的按钮,并展示 属性的用法styled-components。我们有一个样式化的按钮,我们可以添加 属性primary,如下所示:

<Button primary >I am a primary button</Button>

我们的下一步是更新我们的Button定义并为该属性是否primary存在编写一些条件逻辑。

我们可以使用以下结构来实现:

${props => props.primary && css`
`}

我们使用${}来表示我们正在运行某种条件逻辑,并且我们引用了名为 的东西propsprops只是一个包含元素所有属性的字典。正如你上面看到的,我们所说的props.primary真值,它在我们的属性字典中定义。如果是真值,那么我们将应用 CSS 样式。我们可以通过使用 css 函数从上面的代码中识别出后者。

primary下面我们使用上面的构造添加一些样式,只有当属性存在时才应用这些样式:

const Button = styled.button`
  background: black;
  color: white;
  border-radius: 7px;
  padding: 20px;
  margin: 10px;
  font-size: 16px;
  :disabled {
    opacity: 0.4;
  }
  :hover {
    box-shadow: 0 0 10px yellow;
  }
  ${props => props.primary && css`
    background: green;
    color: white;
  `}
`;

现在我们有一个更完整的示例,说明如何测试特定属性是否存在。需要注意的是,我们说过需要使用css函数。这是一个在命名空间中找到的函数styled-components,因此,我们可以通过将 import 语句更新为如下所示来使用它:

import styled, { css } from 'styled-components';

适应

我们已经展示了如何查看某些属性是否存在,但我们也可以根据属性是否存在为属性设置不同的值。

让我们看一下下面的代码,我们border-radius根据是否设置了圆形属性来改变:

const Button = styled.button`
  background: black;
  color: white;
  border-radius: 7px;
  padding: 20px;
  margin: 10px;
  font-size: 16px;
  :disabled {
    opacity: 0.4;
  }
  :hover {
    box-shadow: 0 0 10px yellow;
  }
  ${props => props.primary && css`
    background: green;
    color: white;
  `}
  border-radius: ${props => (props.round ? ‘50%’ : ‘7px’)}
`;

代码中有趣的部分是这样的:

border-radius: ${props => (props.round ? ‘50%’ : ‘7px’)}

我们可以通过像这样声明按钮来触发上述代码的渲染:

<Button round >Round</Button>

为现有组件添加样式

这个方法非常适合用来设置第三方组件或你自己的组件的样式。假设你有以下组件:

// Text.js

import React from 'react';
import PropTypes from 'prop-types';

const Text = ({ text }) => (
  <div> Here is text: {text}</div>
);
Text.propTypes = {
  text: PropTypes.string,
  className: PropTypes.any,
};
export default Text;

现在要给这个样式添加样式,我们需要以稍微不同的方式使用 styled 函数。不要直接输入

styled`` 

我们需要像调用函数一样调用它,并将组件作为参数,如下所示:

const DecoratedText = styled(Text)`
  // define styles
`;
<DecoratedText text={I am now decorated} />

在组件中,我们需要将className作为参数props并将其分配给我们的顶级 div,如下所示:

// Text.js
import React from react;
import PropTypes from prop-types;

const Text = ({ text, className }) => (
  <div className={className}> Here is text: {text}</div>
);
Text.propTypes = {
  text: PropTypes.string,
  className: PropTypes.any,
};
export default Text;

正如您上面所看到的,调用该styled()函数意味着它在底层产生一个className它注入到我们需要设置为顶级元素的组件中,以使其生效。

遗产

我们可以轻松地采用现有样式并使用方法将其添加到其中extend,如下所示:

const GiantButton = Button.extend`
  font-size: 48px;
`;

更改样式的组件

在某些情况下,您可能希望将原本用于特定类型元素的样式应用于其他类型的元素。一个常见的例子是按钮。您可能喜欢特定按钮自带的所有样式,但您可能希望将其应用于锚元素。使用该withComponent()方法可以实现这一点:

const LinkButton = Button.withComponent('a');

上述操作的最终结果是一个锚点,a带有按钮的所有样式的标签。

注意,如果您使用的是 3.0 或更低版本withComponent(),仍然可以这样做。从 4.0 及更高版本开始,建议您使用以下as属性,如下所示:

const Component = styled.div`
  color: red;
`

// Examples
<Component>Hello world!</Component>
<Component as="span">Hello world!</Component>
<Component as={Link} to="home">Hello world!</Component>

使用属性函数

有时你只需要更改组件样式中的一些小细节。为此,该attrs()函数允许你添加一个带有值的属性。让我们演示一下如何添加:

const FramedText = styled(Text).attrs({ title: framed })`
  border: solid 2px black;
  color: blue;
  font-size: 16px;
  padding: 30px;
`;

上面我们把styled()和连接起来,attrs()并以双`勾结束。另一个例子是:

const Button = styled.button.attrs({ title: 'titled' })`
  background: black;
  color: white;
  border-radius: 7px;
  padding: 20px;
  margin: 10px;
  font-size: 16px;
  :disabled {
    opacity: 0.4;
  }
  :hover {
    box-shadow: 0 0 10px yellow;
  }
  ${props => props.primary && css`
    background: green;
    color: white;
  `}
  border-radius: ${props => (props.round ? 50% : 7px)}
`;

 主题

Styled Components 导出一个ThemeProvider,它允许我们轻松地为 Styled Components 添加主题。为了使其正常工作,我们需要执行以下操作:

  • 导入ThemeProvider
  • 将其设置为应用程序的根元素
  • 定义主题
  • 引用主题中的属性并将其设置为所需的 CSS 属性

设置

在我们打算使用 的组件中Theme,我们需要导入并声明ThemeProvider。现在,它可以是整个应用程序的根元素,也可以是你所在的组件。ThemeProvider它会将theme属性注入到所有组件中,或者从你添加它的组件及其所有子组件中注入。让我们看看如何全局添加它:

ReactDOM.render(
  <ThemeProvider theme={{ color: 'white', bgcolor: 'red' }}>
    <App />
  </ThemeProvider>,
  document.getElementById('root'),
);

现在我们准备相应地更改我们的组件以开始使用我们设定的主题。

让我们采用我们定义的 Button 组件并让它使用我们的主题,如下所示:

const Button = styled.button.attrs({ title: 'titled' })`
  background: ${props => props.theme.bgcolor};
  color: ${props => props.theme.color};
  border-radius: 7px;
  padding: 20px;
  margin: 10px;
  font-size: 16px;
  :disabled {
    opacity: 0.4;
  }
  :hover {
   box-shadow: 0 0 10px yellow;
  }
  ${props => props.primary && css`
    background: green;
    color: white;
  `}
  border-radius: ${props => (props.round ? '50%' : '7px')}
`;

让我们详细回顾一下我们所做的事情:

background: ${props => props.theme.bgcolor};
color: ${props => props.theme.color};

正如您所见,我们可以通过写入来访问主题属性props.theme.[nameOfThemeProperty]

主题作为高阶组件工厂

如果我们想在组件内部使用主题,可以这样做,但我们需要使用一个名为 的助手withTheme()。它需要一个组件和 theme 属性,如下所示:

import { withTheme } from 'styled-components';

class TextComponent extends React.Component {
  render() {
    console.log('theme ', this.props.theme);
  }
}
export default withTheme(TextComponent);

概括

我们通过使用库引入了一种设计组件样式的新方法styled-components

className我们还了解到,与使用和分配所述属性 CSS 类的传统样式方式相比,我们可以获得更具语义的组件 DOM 声明。

进一步阅读

官方文档提供了一些关于如何进一步扩展你的知识的优秀示例styled-components 官方文档

希望以上内容能让你相信,这确实是一个设计 React 组件样式的好方法。自从我发现这个库以来,我一直都用它,不过这只是我个人习惯,你自己用吧 :)

链接:https://dev.to/itnext/styled-components-the-styling-library-for-your-react-apps-you-don-t-want-to-be-without-5dlh