styled-components 深入浅出 (二) : 高阶组件

2023-09-01 17:54:24 浏览数 (1)

前言

上篇文章介绍了 styled-components 的一些基础用法,这篇文章接着介绍写它的一些高阶组件用法。

所有相关文章:

《styled-components 深入浅出 (一) : 基础使用》

《styled-components 深入浅出 (二) : 高阶组件》

高阶用法

使用 ThemeProvider 定义主题

通过 ThemeProvider 可以将定义的主题样式注入到组件树中其下方任意位置的所有样式组件中,或者可以说是:将定义的样式作用在被 ThemeProvider 包裹的所有子组件上。

代码语言:javascript复制
const Box = styled.div`
  color: ${props => props.theme.color};
`
代码语言:javascript复制
import {ThemeProvider} from "styled-components";

// theme: 一个对象,将作为 theme 注入到组件树下样式组件的所有插值中。
<ThemeProvider theme={{ color: 'green' }}>
  <Box>ThemeProvider</Box>
</ThemeProvider>

ThemeProvider 中获取当前主题样式 theme

  • 使用 withTheme 高阶组件获取
代码语言:javascript复制
import { withTheme } from 'styled-components'

function MyComponent({theme}){
  return <div>{JSON.stringify(theme)}</div>
}

export default withTheme(MyComponent)
  • 使用 useTheme 钩子函数获取
代码语言:javascript复制
import { useTheme } from 'styled-components'


export default function MyComponent() {
  const theme = useTheme()
  return <div>
    当前自定义主题:
    <br/>
    {JSON.stringify(theme)}
  </div>
}
  • 使用 ThemeConsumer 组件将当前主题样式传递给子函数
代码语言:javascript复制
import { ThemeConsumer } from 'styled-components'

export default function OrderList({theme}) {
  return (
    <ThemeConsumer>
      {theme => <div>The theme color is {theme.color}.</div>}
    </ThemeConsumer>
  )
}

通过 css 方法定义样式

有时候,仅仅是为了给组件添加某个额外的样式,如果通过 styled() 方法创建组件,那就会显得有些繁琐。这时,我们可以通过 css 方法来添加额外组件。它适用于普通 HTML 标签和组件,并支持任何样式化组件(styled component)支持的所有内容,包括基于 props、主题和自定义组件进行调整。 要启用对 css 属性的支持,您必须使用 Babel 插件。

例如:下面的例子:

代码语言:javascript复制
import styled from 'styled-components/macro'

<div
  css={`
    background: papayawhip;
    color: ${props => props.theme.colors.text};
  `}
/>

<Button
  css="padding: 0.5em 1em;"
/>

Babel 插件将任何带有 css 属性的元素转换为样式化组件(styled component)。上面的diamante将会转换成:

代码语言:javascript复制
import styled from 'styled-components';

const StyledDiv = styled.div`
  background: papayawhip;
  color: ${props => props.theme.colors.text};
`

const StyledButton = styled(Button)`
  padding: 0.5em 1em;
`

<StyledDiv />
<StyledButton />

使用 createGlobalStyle 创建全局样式

通常,样式化组件会自动将范围限定为本组件内,样式组件级隔离;而全局样式组件允许我们创建一个样式表,该样式表会作用域全局,所有组件该样式表。

例如:透明通常给 body margin padding 以及动态的修改背景,

代码语言:javascript复制
const GlobalStyle = createGlobalStyle`
  body {
    margin: 0;
    padding: 0;
    background: ${props => (props.$whiteColor ? 'white' : 'black')};
  }
代码语言:javascript复制
<GlobalStyle $whiteColor />

<ThemeProvider> 包裹着的全局样式组件 (<GlobalStyle/>) 也可以访问到 <ThemeProvider> 中定义的主题样式

代码语言:javascript复制
<ThemeProvider theme={{ fontFamily: 'Helvetica Neue' }}>
  <React.Fragment>
    <GlobalStyle $whiteColor />
  </React.Fragment>
</ThemeProvider>

css 函数创建样式块

我们可以通过 css 函数创建一个样式块,该函数接收一个带有 CSS 和插值的标记模板文字的参数,返回一个插值数组,它是一个扁平化的数据结构,我们可以将其作为插值本身进行传递。

代码语言:javascript复制
export const commonCss = css`
  color: white;
  background-color: #1677FF;
  border: none;
  padding: 4px 8px;
  cursor: pointer;
  color:  ${props => props.$color ? props.$color : 'white'};
`

export const MyButton = styled.button`
  ${props => props.$primary ? commonCss : 'color: blue'}
`
代码语言:javascript复制
<MyButton $primary $color="black">按钮</MyButton>

创建动画关键帧

使用 keyframes 函数创建动画关键帧辅助函数,改函数返回要在动画声明中使用的关键帧模型,可以在返回的模型上使用 getName() 获取生成的动画名称

注意: 在 styled-components v3 及以下版本中, keyframes 帮助器直接返回动画名称,而不是使用 getName 方法返回对象。

代码语言:javascript复制
import styled, { keyframes } from 'styled-components'

const fadeIn = keyframes`
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
`

export const FadeInButton = styled.button`
  animation: 1s ${fadeIn} ease-out;
`
代码语言:javascript复制
<FadeInButton>按钮</FadeInButton>

总结

styled-components的一些使用方法基本介绍完了,下篇文章将和大家一起研究,分享一下styled-components源代码是如何实现的。

写在最后

我是 AndyHu,目前暂时是一枚前端搬砖工程师。

文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注呀

0 人点赞