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`
`}
我们使用${}来表示我们正在运行某种条件逻辑,并且我们引用了名为 的东西props。props只是一个包含元素所有属性的字典。正如你上面看到的,我们所说的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