1. 环境安装
# 安装包
yarn add styled-components
# 如果有ts则还需安装
yarn add "@types/styled-components"
2. 引入
import styled from "styled-components";
3. 逐步掌握
1. 普通用法
样式部分
.contact__intro {
font: size 16px;
margin-bottom: 0;
}
.contact__intro strong {
font-weight: 600;
}
标签部分
<p className="contact__intro">
{name} is a <strong>{age} years</strong> old{" "}
<strong>{introduction}</strong>
</p>
使用后:
{/* 样式部分 */}
const ContactIntro = styled.p`
font: size 16px;
margin-bottom: 0;
strong {
font-weight: 600;
}
`;
{/* 标签部分 */}
<ContactIntro>
{name} is a <strong>{age} years</strong> old{" "}
<strong>{introduction}</strong>
</ContactIntro>
2. 变量导入
{/* 标签部分 */}
<Contact gender={gender}>
...
</Contact >
{/* 样式部分 */}
const Contact = styled.div<{ gender: string }>`
border: 1px solid #dedede;
border-radius: 5px;
padding: 15px;
margin: 15px;
background-color: ${(props) =>
props.gender === "female" ? "tomato" : "green"};
color: white;
`;
3. 用attrs封装组件属性,提高代码复用
创建一个简单的密码控件
// 用attrs封装组件属性,提高代码复用
import styled from "styled-components";
const PasswordInput = styled.input.attrs({
type: "password",
padding: (props: { "data-em"?: string }) => props["data-em"] || "0.5em",
margin: (props: { "data-em"?: string }) => props["data-em"] || "0.5em",
})`
border: 2px solid #dedede;
border-radius: 5px;
color: #4a4a4a;
margin: ${(props) => props.margin};
padding: ${(props) => props.padding};
`;
export default PasswordInput;
使用该组件
<PasswordInput name="pass1" />
<PasswordInput name="pass2" data-em="2em" />
4. 实现样式继承
const Contact = styled.div`
border: 1px solid #dedede;
border-radius: 5px;
padding: 15px;
margin: 15px;
color: white;
`;
// 注意 Contact.extend的方法已经被废弃 以下方法相当于继承
// 第二个注意的是styled的值都不用引号引起来
const ContactFemale = styled(Contact)`
background-color: tomato;
`;
const ContactMale = styled(Contact)`
background-color: green;
`;
// 使用
const RenderContact = ({ name, gender, age, introduction }: Props) => {
const ContactComponent = gender === "female" ? ContactFemale : ContactMale;
return (
<ContactComponent>
<ContactName>{name}</ContactName>
<ContactIntro>
{name} is a <strong>{age} years</strong> old{" "}
<strong>{introduction}</strong>
</ContactIntro>
</ContactComponent>
);
};
5. 设置全局样式
injectGlobal已经被废弃,先在用 createGlobalStyle 替代
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
body {
padding: 0;
margin: 0;
color: ${(props) => (props.whiteColor ? "blue" : "black")};
font-family: ${(props) => props.theme.fontFamily};
line-height:2em;
}
`;
ReactDOM.render(
<React.StrictMode>
<App />
<GlobalStyle whiteColor theme={{ fontFamily: "Helvetica Neue" }} />
</React.StrictMode>,
document.getElementById("root")
);
6. 主题设置
import { createGlobalStyle, ThemeProvider } from "styled-components";
const theme = {
primary: "pink",
fontFamily: "Helvetica Neue",
};
ReactDOM.render(
<React.StrictMode>
<ThemeProvider theme={theme}>
<App />
<GlobalStyle whiteColor />
</ThemeProvider>
</React.StrictMode>,
document.getElementById("root")
);
下层组件直接在props中可以获取到theme,如下方式:
const GlobalStyle = createGlobalStyle`
body {
padding: 0;
margin: 0;
color: ${(props) => (props.whiteColor ? "blue" : "black")};
font-family: ${(props) => props.theme.fontFamily};
line-height:2em;
}
`;
7. 动画实现
// 用attrs封装组件属性,提高代码复用
import styled, { keyframes } from "styled-components";
const spin = keyframes`
from {
transform:rotate(0deg);
transform:rotate(359deg);
}`;
const PasswordInput = styled.input.attrs({
type: "password",
padding: (props: { "data-em"?: string }) => props["data-em"] || "0.5em",
margin: (props: { "data-em"?: string }) => props["data-em"] || "0.5em",
})`
border: ${(props) => `2px solid ${props.theme.primary}`};
border-radius: 20px;
color: #4a4a4a;
margin: ${(props) => props.margin};
padding: ${(props) => props.padding};
animation: ${spin} 1s linear infinite;
`;
export default PasswordInput;