使用 styled-components 定义组件样式

styled-components 是一个常用的 css in js 类库。和所有同类型的类库一样,通过 js赋能解决了原生 css所不具备的能力,比如变量、循环、函数等。

动机

  • 自动关联css
  • 可以在样式定义中直接引用到 js 变量,共享变量
  • 自动生成独立的类名,避免重复、重叠或拼写错误
  • 简单的动态样式,不用写很多类名
  • 支持组件之间继承,方便代码复用,提升可维护性
  • 方便样式维护,我们只需定位到某个组件,就能快速改变其样式

安装

执行以下命令便能快速安装依赖:

npm install --save styled-components

或者

yarn add styled-components

基本用法

styled-components使用标签模板来对组件进行样式化。

它移除了组件和样式之间的映射。这意味着,当你定义你的样式时,你实际上只是创建了一个普通的 React 组件,你定义的样式也附在它上面。

下面我们将写两个简单的组件来说明,一个容器组件Wrapper,一个标题H1

Wrapper.js

import styled from "styled-components";

const Wrapper = styled.div`
  height: 200px;
  width: 400px;
  display: flex;
  justify-content: center;
  align-items: center;
  background: aqua;
`;

export default Wrapper;

H1.js

import styled from "styled-components";

const H1 = styled.h1`
  font-size: 32px;
  font-weight: bolder;
  color: chocolate;
`;

export default H1;

App.js

import React from "react";
import ReactDOM from "react-dom";
import Wrapper from "./Wrapper";
import H1 from "./H1";

function App() {
  return (
    
      

Hello,This is a demo of style components!

); } ReactDOM.render(, document.getElementById("root"));

运行程序,我们就能看到如下效果:

使用 styled-components 定义组件样式_第1张图片
style-components-demo.png

此时,h1应用了我们定义的样式。

基于Props做样式判断

模板标签的函数插值能拿到样式组件的 props,可以据此调整我们的样式规则。

第一种方式:

Button.js

import styled from "styled-components";

const Button = styled.button`
  min-width: 64px;
  background: ${props => (props.primary ? "blue" : "transparent")};
  color: ${props => (props.primary ? "white" : "palevioletred")};
  font-size: 14px;
  margin: 8px;
  padding: 8px;
  border: ${props => (props.primary ? "none" : `2px solid palevioletred`)};
  border-radius: 3px;
`;

export default Button;

上述示例中如果primary属性存在,则按钮背景色会变成蓝色,边框消失,并且文字颜色变成白色,使用方式及效果如下:

运行效果:

primary-button.png

此外,我们还可以使用css定义一个样式,然后根据属性判断来调整我们的样式规则,这就有了第二种方式:

Button.js

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

const disabledStyle = css`
  background: transparent;
  color: rgba(0, 0, 0, 0.38);
  border: 2px solid rgba(0, 0, 0, 0.38);
`;

const Button = styled.button`
  min-width: 64px;
  background: ${props => (props.primary ? "blue" : "transparent")};
  color: ${props => (props.primary ? "white" : "palevioletred")};
  font-size: 14px;
  margin: 8px;
  padding: 8px;
  border: ${props => (props.primary ? "none" : `2px solid palevioletred`)};
  border-radius: 3px;
  ${props => props.disabled && disabledStyle};
`;

export default Button;

此时,如果我们给 Button 组件一个disabled属性,则disabledStyle中的样式会自动覆盖原有样式中对应的部分。


运行效果:

disabled-button.png

最后,我们还可以直接传入一个样式属性来控制组件样式的规则,比如,我们希望能自定义按钮的最小宽度,此时我们可以调整Button.js为:

import styled from "styled-components";

const Button = styled.button`
  min-width: ${props => props.minWidth || 64}px;
  background: ${props => (props.primary ? "blue" : "transparent")};
  color: ${props => (props.primary ? "white" : "palevioletred")};
  font-size: 14px;
  margin: 8px;
  padding: 8px;
  border: ${props => (props.primary ? "none" : `2px solid palevioletred`)};
  border-radius: 3px;
`;

export default Button;

此时,只要我们在使用 Button 组件时,给minWidth属性赋值,按钮就会按照我们制定的最小宽度渲染。


mini-button.png

扩展样式

样式扩展主要针对当前组件有部分样式不满足需求的情况,此时我们可以通过样式扩展来进行样式调整,比如:我们希望上面例子中的 Button 组件的边框颜色和字体颜色变成蓝色,此时我们仅仅需要下面一小段代码调整即能满足需求:

const BlueButton = styled(Button)`
  color: blue;
  border: 2px solid blue;
`;
Blue Button
blue-button.png

在某些场景下,我们可能不仅仅只是想要修改组件的样式,甚至想要更新组件的渲染元素,styled-components曾经提供了一种方式来满足我们的需求,即.withComponent()方法。不幸的是在后续版本中,此方法将会被废弃。但令我们欣慰的是:styled-components最新版本为我们提供了一种新的方式,就是as属性。

假设,我们想要使用来渲染我们的 Button 组件,我们仅仅需要在使用 Button 时,赋予一个as属性即可:


运行效果:

link-button.png

同样的,我们也可以使用我们自己定义的其它组件来给as属性赋值。

自定义任意组件的样式

styled-components实际上也是通过className的方式添加样式,所以,只要我们的组件有className,我们就能使用styled-components自定义其样式。

import React from "react";
import styled from "styled-components";

const P = ({ className, children }) => 

{children}

; const CustomP = styled(P)` color: blue; font-size: 32px; `; export { P, CustomP };

App.js

这是一段普通的文本内容

这是一段自定义样式的文本内容

运行效果:

使用 styled-components 定义组件样式_第2张图片
custom-style.png

使用.attrs添加属性

我们可以使用attrsAPI 来为样式组件添加一些属性,它们也可以通过标签模板插值函数拿到 props 传值。

import styled from "styled-components";

const PasswordInput = styled.input.attrs({
  type: "password",
  margin: props => props.size || "1em",
  padding: props => props.size || "1em"
})`
  color: palevioletred;
  font-size: 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
  margin: ${props => props.margin};
  padding: ${props => props.padding};
`;

export default PasswordInput;

App.js


运行效果:

password-input.png

动画

带有@keyframesCSS animations,一般来说会产生复用。styled-components暴露了一个keyframesAPI,我们使用它产生一个可以复用的变量。这样,我们在书写css样式的时候使用 JavaScript 的功能,为CSS附能,并且避免了名称冲突。

import styled, { keyframes } from "styled-components";

const rotateStyle = keyframes`
    from {
    transform: rotate(0deg);
  }

    to {
    transform: rotate(360deg);
  }
`;

const Rotate = styled.div`
  display: inline-block;
  animation: ${rotateStyle} 2s linear infinite;
  padding: 2rem 1rem;
  font-size: 1.2rem;
`;

export default Rotate;

App.js

旋转

运行效果:

rotate.gif

父组件中定义子组件样式

styled-components提供了component selector组件选择器模式来代替我们以往对 class 名的依赖。

开篇的示例,如果我们想要在 Wrapper 中改变H1的颜色为白色,可以有下面两种方式:

第一种,通过h1查找,并修改样式:

Wrapper.js

const Wrapper = styled.div`
  height: 200px;
  width: 400px;
  display: flex;
  justify-content: center;
  align-items: center;
  background: aqua;

  > h1 {
    color: white;
  }
`;

第二种,通过H1的组件名查找元素并修改样式:

const Wrapper = styled.div`
  height: 200px;
  width: 400px;
  display: flex;
  justify-content: center;
  align-items: center;
  background: aqua;

  ${H1} {
    color: white;
  }
`;

App.js


  

Hello,This is a demo of style components!

以上两种方式运行效果如下:

使用 styled-components 定义组件样式_第3张图片
css-in-parent.png

注意:下面这种方式不支持在父组件中定义自组件样式

class A extends React.Component {
  render() {
    return 
; } } const B = styled.div` ${A} { } `;

因为 A 继承ReactComponent,不是被 styled 构造过的。我们的组件选择器只支持在Styled Components创建的样式组件。

附注

有时候可能由于优先级的问题,我们自定义的样式无法使用,此时我们只需要使用&&就能提升其优先级:

const CustomButton = styled(Button)`
  && {
    width: 88px;
  }
`;

总结

这篇文章主要介绍了styled-components的基本用法,包括通过属性控制样式规则、样式扩展、自定义组件样式、使用.attrs添加属性、动画等,希望可以通过阅读此文章数量掌握如何使用styled-components定义组件样式。

查看示例源码

参考文章

styled-components 官网

Styled-Components

你可能感兴趣的:(使用 styled-components 定义组件样式)