感谢 Liang Wang 提供中文翻译文档
https://github.com/hengg/styled-components-docs-zh/blob/master/Basics.md
我在这里精简一下基础部分,方便快速回顾知识,没学过的还是建议先看文档
安装 yarn add styled-components
引入 import styled from 'styled-components'
先来个最基础的例子
// 创建一个 Title 组件,它将渲染一个附加了样式的 标签
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
// 创建一个 Wrapper 组件,它将渲染一个附加了样式的 标签
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
// 就像使用常规 React 组件一样使用 Title 和 Wrapper
render(
Hello World!
);
先解析第一行 styled
是引入的styled,.
后面的是你要创建的标签名,` `
中间包裹的就是正常的CSS样式(可以写变量,传props值,后面会讲到),然后你这些复制给一个大写开头的Title变量,那么Title在styled的作用下就变成了一个组件,直接把组件渲染出来就可以了
基于属性的适配
const Button = styled.button`
/* Adapt the colors based on primary prop */
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
render(
);
样式继承
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// 一个继承 Button 的新组件, 重载了一部分样式
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;
render(
Tomato Button
);
多态 "as" polymorphic prop
const Button = styled.button`
display: inline-block;
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;
render(
Link with Tomato Button styles
);
这也完美适用于自定义组件:
const Button = styled.button`
display: inline-block;
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
const ReversedButton = props =>
render(
);
给任何组件添加样式
styled方法适用于任何最终向 DOM 元素传递 className 属性的组件,当然也包括第三方组件.
注意
在 react-native 中,请使用 style 而不是 className.
// 下面是给 react-router-dom Link 组件添加样式的示例
const Link = ({ className, children }) => (
{children}
);
const StyledLink = styled(Link)`
color: palevioletred;
font-weight: bold;
`;
render(
Unstyled, boring Link
Styled, exciting Link
);
也可以传递标签给styled(), 比如: styled("div"). 实际上styled.tagname的方式就是 styled(tagname)`的别名.
属性传递
const Input = styled.input`
padding: 0.5em;
margin: 0.5em;
color: ${props => props.inputColor || "palevioletred"};
background: papayawhip;
border: none;
border-radius: 3px;
`;
// 渲染两个样式化的 text input,一个标准颜色,一个自定义颜色
render(
);
注意, inputColor prop并没有传递给 DOM, 但是type和defaultValue 都传递了. styled-components足够智能,会自动过滤掉所有非标准 attribute.
styled-components 如何在组件中工作?
Styled Component 是 HTML 元素和作用在元素上的样式规则的组合, 我们可以这样编写Counter:
import React from 'react'
import styled from 'styled-components'
const StyledCounter = styled.div`
/* ... */
`
const Paragraph = styled.p`
/* ... */
`
const Button = styled.button`
/* ... */
`
export default class Counter extends React.Component {
state = { count: 0 }
increment = () => this.setState({ count: this.state.count + 1 })
decrement = () => this.setState({ count: this.state.count - 1 })
render() {
return (
{this.state.count}
)
}
}
伪元素,伪类选择器和嵌套
styled-component
所使用的预处理器stylis支持自动嵌套的 scss-like 语法,示例如下:
const Thing = styled.div`
color: blue;
`
伪元素和伪类无需进一步细化,而是自动附加到了组件:
const Thing = styled.button`
color: blue;
::before {
content: '';
}
:hover {
color: red;
}
`
render(
Hello world!
)
对于更复杂的选择器,可以使用与号(&)来指向主组件.以下是一些示例:
const Thing = styled.div.attrs({ tabIndex: 0 })`
color: blue;
&:hover {
color: red; // when hovered
}
& ~ & {
background: tomato; // as a sibling of , but maybe not directly next to it
}
& + & {
background: lime; // next to
}
&.something {
background: orange; // tagged with an additional CSS class ".something"
}
.something-else & {
border: 1px solid; // inside another element labeled ".something-else"
}
`
如果只写选择器而不带&,则指向组件的子节点.
const Thing = styled.div`
color: blue;
.something {
border: 1px solid; // an element labeled ".something" inside
display: block;
}
`
render(
)
附加额外的属性 (v2)
为了避免仅为传递一些props来渲染组件或元素而使用不必要的wrapper, 可以使用 .attrs
constructor. 通过它可以添加额外的 props 或 attributes 到组件.
举例来说,可以通过这种方式给元素添加静态 props,或者传递第三方 prop 给组件(比如传递activeClassName
给 React Router 的 Link
). 此外也可以将dynamic props 添加到组件. .attrs
对象也接收函数,返回值也将合并进 props.
示例如下:
source-js-jsx
const Input = styled.input.attrs({
// static props
type: "password",
// dynamic props
margin: props => props.size || "1em",
padding: props => props.size || "1em"
})`
color: palevioletred;
font-size: 1em;
border: 2px solid palevioletred;
border-radius: 3px;
/* dynamically computed props */
margin: ${props => props.margin};
padding: ${props => props.padding};
`;
render(
);
动画
虽然使用@keyframes的 CSS 动画不限于单个组件,但我们仍希望它们不是全局的(以避免冲突). 这就是为什么 styled-components 导出 keyframes helper 的原因: 它将生成一个可以在 APP 应用的唯一实例:
// Create the keyframes
const rotate = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
// Here we create a component that will rotate everything we pass in over two seconds
const Rotate = styled.div`
display: inline-block;
animation: ${rotate} 2s linear infinite;
padding: 2rem 1rem;
font-size: 1.2rem;
`;