本文作为 2020年的css周边:preprocessor、css-in-js等解决方案与methodology 的一部分用来说明css-in-js的用法,欢迎阅读
什么是styled-components
styled-components是一个js库,以下简称SC,我们可以利用其提供的api编写css以增强react组件系统的样式功能,其他css-in-js解决方案的思路也类似。
基本用法如下
//创建一个组件
import styled from 'styled-components';
const Title = styled.h1`
font-size: 1.5em;
`;
//将刚创建的组件像其他react组件一样正常使用
render(
<Title>
Hello World!
</Title>
);
SC处理过css以后为我们提供了以下
- 追踪页面上渲染的组件自动注入样式,结合代码拆分可以加载尽量少的代码。
- 会生成独一无二的class names,不用担心重复、覆盖,这也是css-modules要实现的功能
- 可以很清晰的知道哪些代码用了指定样式,更改或删除等维护方便
- 基于props或者全局变量动态设置样式
- 自动添加浏览器特定的前缀
基本原理
如果要学习一个js库,比使用更重要的是明白其原理,而使用只是在调用原理基础上暴露出来的api,因此这里对基本实现做一下简要介绍。
首先styled.h1``
语法被称为Tagged Template Literal,类似直接函数调用styled.h1()
(在SC中的具体作用参考The magic behind 💅 styled-components),它本质上就是一个组件工厂,用来返回各种带有我们自定义样式的组件。
当react开始渲染组件,即调用styled.h1
,这相当于执行styled('h1')([样式])
(因为在styled初始化时中将对应方法挂载到了上面),然后通过调用createStyledComponent方法经过一系列步骤生成组件提供给react。
在组件创建过程中会
- 计算tagged template,获取
componentStyle
- 根据
componentId
和componentStyle
等计算className - 使用STYLIS对样式添加浏览器对应前缀等预处理
- 将生成的样式添加到style标签
- 创建一个对应className的元素
通过对SC较为简单的分析,我们已经对其执行过程有了初步认识,现在我们看一下具体用法
指南
基本使用
除了上面介绍的用法还有
使用props
可以添加一个函数插值,其中参数就是props,比如
const Button = styled.button`
/* Adapt the colors based on primary prop */
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};
`;
render(
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);
扩展样式
以一个组件为基础生成另一个组件,基础组件可以是任意组件
//Button是一个组件
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;
来自css的样式
可以将css文件中的样式导入使用,就像在使用cssModule一样
import styles from './styles.css'
<h1 className="title">
Hello World
</h1>
//styles.css
.title {
color: red;
}
伪类、伪元素和嵌套
SC依赖的stylis
可以提供类sass的语法来提供以上功能(想回顾sass的语法,请参考2020年的css周边之sass用法指南)
添加另外的或者重写props
使用.attrs
方法添加另外的props
const Input = styled.input.attrs(props => ({
// we can define static props
type: "text",
// or we can define dynamic ones
size: props.size || "1em",
}))`
padding: ${props => props.size};
`;
render(
<div>
<Input placeholder="A small text input" />
<br />
<Input placeholder="A bigger text input" size="2em" />
</div>
);
一些技巧
- 用高优先级覆盖样式
const MyStyledComponent = styled(AlreadyStyledComponent)`
&&& {
color: palevioletred;
font-weight: bold;
}
`
每个&
都会生成一个类,比如
.MyStyledComponent-asdf123.MyStyledComponent-asdf123.MyStyledComponent-asdf123 {
color: palevioletred;
font-weight: bold;
}
- 覆盖行内样式
const MyStyledComponent = styled(InlineStyledComponent)`
&[style] {
font-size: 12px !important;
color: blue !important;
}
`
结语
SC作为一个js库,相对于sass这种语言级别的工具,内容很少,更多用法请参考SC官方文档,现在可以继续去阅读2020年的css周边:preprocessor、css-in-js等解决方案与methodology其他部分啦🎨!