使用样式系统和样式组件创建一个高度可重复使用的按钮。

2025-06-09

使用样式系统和样式组件创建一个高度可重复使用的按钮。

如果你曾经使用过Chakra UIMaterial UI之类的组件库,你可能知道这些库有多么直观。我一直想创建像这些库公开的组件一样可复用的组件。今天,我们将创建我们自己的酷炫可复用按钮组件😎。

首先,让我们列出我们期望可重复使用按钮具备的功能。对我来说,我希望能够自定义颜色、字体、大小、间距、布局等等。

首先安装要用到的库,并简要介绍一下每个库的功能。styled-componentsstyled-components是一个 CSS-in-JS 库,允许你在 JavaScript 中编写作用域限定于一个组件的 CSS。它可以说是 CSS 模块的继承者。我们来看一个如何使用 styled-components 的示例。

import styled from 'styled-components'

const Button = styled.button`
  background: transparent;
  border-radius: 3px;
  border: 2px solid palevioletred;
  color: palevioletred;
  margin: 0 1em;
  padding: 0.25em 1em;
`
Enter fullscreen mode Exit fullscreen mode

现在,无论何时您想使用该按钮,只需像常规反应组件一样导入它即可。styled-components 允许您传递 props 进行自定义,因此,例如,如果您想根据 prop 更改按钮的字体大小,您可以这样做。

import styled, { css } from 'styled-components'

const Button = styled.button`
  background: transparent;
  border-radius: 3px;
  border: 2px solid palevioletred;
  color: palevioletred;
  margin: 0 1em;
  padding: 0.25em 1em;
  ${props => props.fontSize ? css`
          font-size: props.fontSize;             
`: ''}
`
Enter fullscreen mode Exit fullscreen mode

当我们想要将自定义字体大小传递给此组件时,您可以这样做。

<Button fontSize='2rem'>My button</Button>
Enter fullscreen mode Exit fullscreen mode

你可以想象一下,仅仅利用这个 API,我们就能构建动态组件。我喜欢这种构建组件的方式,但如果我们添加 styled-system,就能创建更加健壮的组件。

在使用 styled-system 之前,我们先来定义一下它是什么。根据其文档, styled-system 是一组实用函数,它们可以向 React 组件添加样式属性,并允许你基于全局主题对象控制样式,该对象包含字体比例、颜色和布局属性。styled-system 可以与 styled-components 之类的 CSS-in-JS 库配合使用。

让我们看一个基本的例子。

import styled from 'styled-components'
import { color } from 'styled-system'

const Box = styled.div`
  ${color}
`
Enter fullscreen mode Exit fullscreen mode

现在,此组件将有两个可用的样式属性:color设置前景色和bg设置背景色。(您也可以使用backgroundColor)。

<Box color="#eee" bg="orange">
  Orange
</Box>
Enter fullscreen mode Exit fullscreen mode

现在我们对 styled-components 和 styled-system 的工作原理有了基本的了解,让我们开始创建我们的<Button/>组件。

import styled from 'styled-components'
import { color } from 'styled-system'

const Button = styled.button`
    border: 0;
    outline: 0;
    ${color}
 `
Enter fullscreen mode Exit fullscreen mode

这使我们能够像这样设置按钮的样式,

<Button color="white" backgroundColor="tomato">
  Hello, world!
</Button>
Enter fullscreen mode Exit fullscreen mode

添加间距和字体大小

import styled from 'styled-components'
import { color, space, fontSize } from 'styled-system'

const Button = styled.button`
   border: 0;
   outline: 0;
   ${color}
   ${space}
   ${fontSize}
 `
Enter fullscreen mode Exit fullscreen mode

现在您可以自定义填充、字体大小和边距。下面是如何使用按钮的示例。

<Button color="white" backgroundColor="tomato" px='2rem' mr='1rem' fontSize='2rem'>
  Hello, world!
</Button>
Enter fullscreen mode Exit fullscreen mode

正如你所见,我们的组件变得越来越实用,但你可能不想在使用它时传递所有这些 props。这时,默认 props 和主题就派上用场了。

让我们创建一个带有颜色的基本主题并将默认道具传递给我们的按钮。

import styled, { ThemeProvider } from 'styled-components'
import { color, space, fontSize } from 'styled-system'

const theme = {
  colors: {
    custom: '#444',
    yellow: 'yellow'
  }
}

const Button = styled.button`
   border: 0;
   outline: 0;
   ${color}
   ${space}
   ${fontSize}
 `
Button.defaultProps = {
  backgroundColor: 'blue'
}

const App = () => {
  return (
    <ThemeProvider theme={theme}>
      <Button color='custom'>Styled Button</Button>
    </ThemeProvider>
  )
}
Enter fullscreen mode Exit fullscreen mode

从这段代码可以看出,所有按钮的背景都是蓝色,因为我们将其作为默认属性传递了。将 bg 或 backgroundColor 属性传递给按钮将覆盖默认的 backgroundColor 属性。

对于按钮,我们通常希望传递 variant 属性来进一步自定义按钮。样式系统中的 buttonStyle 函数允许我们添加 variant 属性,这在我们扩展主题时非常有用。以下代码演示了这一点。

import styled, { ThemeProvider } from 'styled-components'
import { color, space, fontSize, buttonStyle } from 'styled-system'

const theme = {
  colors: {
    custom: '#444',
    yellow: 'yellow'
  },
 buttons: {
    primary: {
      color: 'white',
      backgroundColor: 'blue'
    },
    secondary: {
      color: 'white',
      backgroundColor: 'green'
    }  
  }
}

const Button = styled.button`
   border: 0;
   outline: 0;
   ${color}
   ${space}
   ${fontSize}
   ${buttonStyle}
 `
Button.defaultProps = {
  variant: 'primary',
  backgroundColor: 'blue'
}

const App = () => {
  return (
    <ThemeProvider theme={theme}>
      <Button color='custom' variant='secondary'>Styled Button</Button>
    </ThemeProvider>
  )
}
Enter fullscreen mode Exit fullscreen mode

添加自定义道具

如果你想给按钮传递一个像 size 这样的属性,让它变成 small、medium 或 large 呢?样式良好的样式系统允许我们通过 variant 函数来实现。下面是我们将所有这些功能组合在一起的最终代码。请注意,这只是一个基础按钮,你甚至可以根据需要添加更多功能。

import styled, { ThemeProvider } from 'styled-components'
import { color, space, fontSize, buttonStyle, variant } from 'styled-system'

const buttonSize = variant({
  prop: 'size',
  key: 'buttonSizes'
})

const theme = {
  colors: {
    custom: '#444',
    yellow: 'yellow'
  },
 buttons: {
    primary: {
      color: 'white',
      backgroundColor: 'blue'
    },
    secondary: {
      color: 'white',
      backgroundColor: 'green'
    }  
  },
buttonSizes: {
    small: {
      fontSize: '15px',
      padding: `7px 15px`
    },
    medium: {
      fontSize: '18px',
      padding: `9px 20px`
    },
    large: {
      fontSize: '22px',
      padding: `15px 30px`
    }
  }
}

const Button = styled.button`
   border: 0;
   outline: 0;
   ${color}
   ${space}
   ${fontSize}
   ${buttonStyle}
 `
Button.defaultProps = {
  variant: 'primary',
  backgroundColor: 'blue',
  size: 'medium'
}

const App = () => {
  return (
    <ThemeProvider theme={theme}>
      <Button color='custom' variant='secondary' size='large'>Styled Button</Button>
    </ThemeProvider>
  )
}
Enter fullscreen mode Exit fullscreen mode
链接链接 https://dev.to/josemukorivo/create-a-highly-reusable-button-with-styled-system-and-styled-components-45lm
PREV
为什么没有人谈论 Razzle?
NEXT
Neon 与 create-t3-app 相遇:面向现代开发者的 PostgreSQL 解决方案:Neon 作为数据库提供程序 #1976 create-neon-t3