Chakra Factory 组件工厂 #

什么是 Chakra Factory? #

Chakra Factory 是一个强大的工具函数,它可以将任意 HTML 元素或第三方组件转换为支持 Chakra Style Props 的组件。

jsx
import { chakra } from '@chakra-ui/react'

const StyledSection = chakra('section')

function App() {
  return (
    <StyledSection p={4} bg="blue.500" color="white">
      支持 Style Props 的 section 元素
    </StyledSection>
  )
}

基本用法 #

转换 HTML 元素 #

jsx
import { chakra } from '@chakra-ui/react'

const StyledHeader = chakra('header')
const StyledFooter = chakra('footer')
const StyledNav = chakra('nav')
const StyledArticle = chakra('article')

function BlogPost() {
  return (
    <StyledHeader bg="gray.100" p={4}>
      <StyledNav display="flex" gap={4}>
        导航栏
      </StyledNav>
    </StyledHeader>
  )
}

转换第三方组件 #

jsx
import { chakra } from '@chakra-ui/react'
import { Link as RouterLink } from 'react-router-dom'

const StyledLink = chakra(RouterLink)

function Navigation() {
  return (
    <StyledLink
      to="/home"
      color="blue.500"
      _hover={{ color: 'blue.600' }}
      fontWeight="medium"
    >
      首页
    </StyledLink>
  )
}

chakra 函数 #

语法 #

jsx
chakra(element, options?)

参数 #

参数 类型 说明
element string | ReactComponent HTML 标签名或 React 组件
options object 配置选项

示例 #

jsx
import { chakra } from '@chakra-ui/react'

const StyledButton = chakra('button', {
  baseStyle: {
    px: 4,
    py: 2,
    borderRadius: 'md',
    fontWeight: 'medium',
  },
})

内置 Chakra 元素 #

Chakra UI 已经为所有 HTML 元素提供了 chakra 版本:

jsx
import { chakra } from '@chakra-ui/react'

function App() {
  return (
    <chakra.div p={4} bg="gray.100">
      <chakra.h1 fontSize="2xl" mb={4}>
        标题
      </chakra.h1>
      <chakra.p color="gray.600">
        段落内容
      </chakra.p>
      <chakra.button
        mt={4}
        px={4}
        py={2}
        bg="blue.500"
        color="white"
        borderRadius="md"
        _hover={{ bg: 'blue.600' }}
      >
        按钮
      </chakra.button>
    </chakra.div>
  )
}

可用的 Chakra 元素 #

jsx
<chakra.div />
<chakra.span />
<chakra.p />
<chakra.h1 />
<chakra.h2 />
<chakra.h3 />
<chakra.h4 />
<chakra.h5 />
<chakra.h6 />
<chakra.button />
<chakra.input />
<chakra.textarea />
<chakra.select />
<chakra.a />
<chakra.img />
<chakra.ul />
<chakra.ol />
<chakra.li />
<chakra.table />
<chakra.thead />
<chakra.tbody />
<chakra.tr />
<chakra.td />
<chakra.th />
<chakra.form />
<chakra.label />
<chakra.section />
<chakra.article />
<chakra.header />
<chakra.footer />
<chakra.nav />
<chakra.main />
<chakra.aside />

创建可复用组件 #

基础组件 #

jsx
import { chakra } from '@chakra-ui/react'

export const Card = chakra('div', {
  baseStyle: {
    p: 6,
    bg: 'white',
    borderRadius: 'lg',
    shadow: 'md',
  },
})

export const CardTitle = chakra('h3', {
  baseStyle: {
    fontSize: 'xl',
    fontWeight: 'bold',
    mb: 2,
  },
})

export const CardText = chakra('p', {
  baseStyle: {
    color: 'gray.600',
    lineHeight: 'tall',
  },
})

使用组件 #

jsx
import { Card, CardTitle, CardText } from './components'

function ProductCard() {
  return (
    <Card>
      <CardTitle>产品名称</CardTitle>
      <CardText>产品描述信息</CardText>
    </Card>
  )
}

与第三方库集成 #

React Router #

jsx
import { chakra } from '@chakra-ui/react'
import { Link as RouterLink, NavLink as RouterNavLink } from 'react-router-dom'

export const Link = chakra(RouterLink, {
  baseStyle: {
    color: 'blue.500',
    textDecoration: 'none',
    _hover: {
      textDecoration: 'underline',
    },
  },
})

export const NavLink = chakra(RouterNavLink, {
  baseStyle: {
    px: 3,
    py: 2,
    borderRadius: 'md',
    color: 'gray.600',
    _hover: {
      bg: 'gray.100',
    },
    _activeLink: {
      bg: 'blue.50',
      color: 'blue.600',
    },
  },
})

Framer Motion #

jsx
import { chakra } from '@chakra-ui/react'
import { motion } from 'framer-motion'

const MotionBox = chakra(motion.div)

function AnimatedCard() {
  return (
    <MotionBox
      p={6}
      bg="white"
      borderRadius="lg"
      shadow="md"
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.3 }}
    >
      动画卡片
    </MotionBox>
  )
}

React Icons #

jsx
import { chakra } from '@chakra-ui/react'
import { FiHome, FiUser, FiSettings } from 'react-icons/fi'

const Icon = chakra(FiHome)

function IconExample() {
  return (
    <>
      <Icon boxSize={6} color="blue.500" />
      <chakra(FiUser) boxSize={5} color="green.500" />
      <chakra(FiSettings) boxSize={4} color="gray.500" />
    </>
  )
}

高级用法 #

使用 forwardRef #

jsx
import { chakra, forwardRef } from '@chakra-ui/react'

const Input = forwardRef((props, ref) => {
  return (
    <chakra.input
      ref={ref}
      px={4}
      py={2}
      border="1px solid"
      borderColor="gray.200"
      borderRadius="md"
      _focus={{
        borderColor: 'blue.500',
        outline: 'none',
      }}
      {...props}
    />
  )
})

使用 shouldForwardProp #

jsx
import { chakra } from '@chakra-ui/react'

const CustomComponent = chakra('div', {
  shouldForwardProp: (prop) => {
    return !['customProp'].includes(prop)
  },
})

使用 themeKey #

jsx
import { chakra } from '@chakra-ui/react'

const Heading = chakra('h2', {
  themeKey: 'components.Heading',
})

实用示例 #

创建按钮变体 #

jsx
import { chakra } from '@chakra-ui/react'

const Button = chakra('button', {
  baseStyle: {
    px: 4,
    py: 2,
    borderRadius: 'md',
    fontWeight: 'medium',
    transition: 'all 0.2s',
    _focus: {
      outline: 'none',
      ring: '2px',
      ringOffset: '2px',
    },
    _disabled: {
      opacity: 0.5,
      cursor: 'not-allowed',
    },
  },
})

const PrimaryButton = chakra(Button, {
  baseStyle: {
    bg: 'blue.500',
    color: 'white',
    _hover: { bg: 'blue.600' },
    _active: { bg: 'blue.700' },
  },
})

const SecondaryButton = chakra(Button, {
  baseStyle: {
    bg: 'gray.100',
    color: 'gray.800',
    _hover: { bg: 'gray.200' },
    _active: { bg: 'gray.300' },
  },
})

创建布局组件 #

jsx
import { chakra } from '@chakra-ui/react'

export const Container = chakra('div', {
  baseStyle: {
    w: '100%',
    mx: 'auto',
    maxW: 'container.lg',
    px: 4,
  },
})

export const Section = chakra('section', {
  baseStyle: {
    py: 16,
  },
})

export const Grid = chakra('div', {
  baseStyle: {
    display: 'grid',
    gap: 6,
    gridTemplateColumns: {
      base: '1fr',
      md: 'repeat(2, 1fr)',
      lg: 'repeat(3, 1fr)',
    },
  },
})

创建表单组件 #

jsx
import { chakra, forwardRef } from '@chakra-ui/react'

export const FormLabel = chakra('label', {
  baseStyle: {
    display: 'block',
    mb: 2,
    fontSize: 'sm',
    fontWeight: 'medium',
    color: 'gray.700',
  },
})

export const FormInput = forwardRef((props, ref) => (
  <chakra.input
    ref={ref}
    w="100%"
    px={4}
    py={2}
    border="1px solid"
    borderColor="gray.300"
    borderRadius="md"
    _placeholder={{ color: 'gray.400' }}
    _focus={{
      borderColor: 'blue.500',
      ring: '2px',
      ringColor: 'blue.200',
    }}
    {...props}
  />
))

export const FormHelper = chakra('p', {
  baseStyle: {
    mt: 1,
    fontSize: 'sm',
    color: 'gray.500',
  },
})

export const FormError = chakra('p', {
  baseStyle: {
    mt: 1,
    fontSize: 'sm',
    color: 'red.500',
  },
})

最佳实践 #

1. 命名约定 #

jsx
const StyledButton = chakra('button')
const ChakraLink = chakra(RouterLink)

2. 导出可复用组件 #

jsx
export const Card = chakra('div', {
  baseStyle: {
    p: 6,
    bg: 'white',
    borderRadius: 'lg',
    shadow: 'md',
  },
})

3. 组合使用 #

jsx
import { Box } from '@chakra-ui/react'
import { chakra } from '@chakra-ui/react'

const CustomBox = chakra(Box)

下一步 #

现在你已经掌握了 Chakra Factory,接下来学习 CSS Reset,了解如何统一浏览器默认样式!

最后更新:2026-03-28