- 文档
- 知识库
- 教程
- 开发工具
【免费下载链接】reference
为开发人员分享快速参考备忘清单(速查表)
本指南以 jaywcjlove/reference 仓库中的 docs/styled-components.md 为主体,系统梳理 CSS-in-JS 工具 styled-components 在 React 组件系统中的全部常用技法。从安装、基础组件创建、Props 适配、样式扩展,到 TypeScript 类型方案、React Native 写法与主题化高级用法,读完本文你将能独立用 styled-components 写出类型安全、可复用、可主题化的组件样式。
入门
安装
styled-components 是增强 CSS 在 React 组件系统样式的 CSS-in-JS 主流实践方案。它允许你在 JavaScript/TypeScript 中直接书写真正的 CSS,并将其绑定到组件上,同时自动处理样式作用域隔离、关键帧命名和样式注入。
安装运行时依赖与 TypeScript 类型依赖:
npm install --save styled-components为获得更好的开发体验,可搭配官方维护的编辑器插件(均提供语法高亮,部分支持自动补全):
- VSCode 插件:提供代码高亮与代码提示(styled-components 官方维护)
- VIM 插件:提供代码高亮
- WebStorm 插件:提供代码高亮与代码提示
快速开始
在组件文件中引入 styled 默认导出:
import styled from 'styled-components';创建一个 Title 组件:
// 该组件将呈现具有样式的 <h1> 标签 const Title = styled.h1` font-size: 1.5em; text-align: center; `;创建一个 Wrapper 组件:
// 该组件将呈现具有某些样式的 <section> 标记 const Wrapper = styled.section` padding: 4em; background: papayawhip; `;像使用其他 React 组件一样使用 Title / Wrapper —— 除了它们自带样式:
function Demo() { return ( <Wrapper> <Title> Hello World! </Title> </Wrapper> ); }这里styled.h1、styled.section是通过标签模板(tagged template)语法接收 CSS 字符串的工厂函数,返回一个带着样式的 React 组件。底层通过为组件生成稳定的唯一类名,并将样式规则注入<head>,从而实现样式与组件的一一对应。
根据 Props 适配
样式模板内的插值函数会接收组件自身的props,据此动态产出 CSS,这是 styled-components 实现"状态驱动样式"的核心机制:
import styled from 'styled-components'; const Button = styled.button` /* 根据主要 props 调整颜色 */ background: ${ props => props.primary ? "blue" : "white" }; color: ${ props => props.primary ? "white" : "blue" }; font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid blue; border-radius: 3px; `;使用primaryprops 控制按钮样式:
function Demo() { return ( <div> <Button>Normal</Button> <Button primary>Primary</Button> </div> ); }当primary为真时,按钮呈现蓝底白字;否则为白底蓝字。插值函数接收到的props与组件渲染时的 props 完全一致,因此可以读取任意自定义属性来做条件样式。
扩展样式
基于已有 styled 组件创建新组件,新组件继承原组件全部样式,再叠加(或覆盖)新规则。这种继承是样式层面上的"类继承",非常适合构建基础组件库:
const Button = styled.button` color: palevioletred; border: 2px solid palevioletred; border-radius: 3px; `; // 基于 Button 的新组件,但具有一些覆盖样式 const TomatoButton = styled(Button)` color: tomato; border-color: tomato; `; const Demo = () => ( <div> <Button>普通按钮</Button> <TomatoButton>番茄色按钮</TomatoButton> </div> );styled(Button)接收一个已存在的组件作为目标,返回继承其样式的增强组件。
扩展样式改变标签 (as)
通过as属性,可以在不改变既有样式的前提下,把渲染的 DOM 标签切换为其他标签。例如让<button>以<a>的形式渲染,样式完全不变:
const Button = styled.button` color: palevioletred; padding: 0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; display: block; `; const TomatoButton = styled(Button)` color: tomato; border-color: tomato; `; const Demo = () => ( <div> <Button>普通按钮</Button> <Button as="a" href="#"> 按钮样式的链接 </Button> <TomatoButton as="a" href="#"> 番茄按钮样式的链接 </TomatoButton> </div> );as也可以用于扩展出来的组件(如TomatoButton),灵活组合标签与样式。
自定义组件(as)
as除了接收字符串标签名,还可以接收任意自定义 React 组件。此时自定义组件将获得 styled 组件生成的 className,并沿用其全部样式:
const Button = styled.button` color: palevioletred; font-size: 1em; border: 2px solid palevioletred; display: block; `; const ReversedButton = props => ( <Button {...props} children={ props.children.split('').reverse() } /> ); render( <div> <Button>普通按钮</Button> <Button as={ReversedButton}> 具有普通按钮样式的自定义按钮 </Button> </div> );ReversedButton作为自定义组件接收了 Button 的样式类,同时自身实现了"把子文本倒序显示"的额外逻辑——样式与行为被优雅地解耦。
样式化任何组件
任何接收className属性的组件都可以被 styled 化。关键约定:目标组件必须把className透传到其渲染的真实 DOM 元素上,否则样式无法生效:
const Link = ({ className, children }) => ( <a className={className}> {children} </a> ); const StyledLink = styled(Link)` color: palevioletred; font-weight: bold; `; <StyledLink className="hello" />这也是编写可被 styled 化的第三方/自有组件的通用模式:通过className入口承接外部样式。
在 render 之外定义 Styled 组件
styled 组件必须在模块顶层(或 render 之外)定义,绝不能在组件函数体内创建:
const Box = styled.div`/* ... */`; const Wrapper = ({ message }) => { // ⚠️ 不能在这里定义 styled 组件 return ( <Box> {message} </Box> ); };注意:组件Box不能放到Wrapper函数组件里面。原因在于 styled 组件内部依赖稳定的组件身份(component identity)做缓存、class 生成与样式去重;每次 render 都重新创建会导致 React 卸载/重挂载整个子树,产生样式闪烁与性能退化。
传入值
把外部传入的值通过 props 插值直接写入样式,未传时使用默认值:
const Input = styled.input` color: ${ props => props.inputColor || "palevioletred" }; background: papayawhip; `; const Demo = () => ( <div> <Input defaultValue="@probablyup" type="text" /> <Input defaultValue="@geelen" type="text" inputColor="rebeccapurple" /> </div> );未传inputColor的第一个输入框使用默认色palevioletred,传了inputColor="rebeccapurple"的第二个输入框则使用自定义颜色。
样式对象
插值函数也可以直接返回一个 CSS 属性对象(camelCase 键名),而不是 CSS 字符串:
const PropsBox = styled.div(props => ({ background: props.background, height: '50px', width: '50px', fontSize: '12px' }));在组件中使用:
const Example = () => { return ( <div> <PropsBox background="blue" /> </div> ); }注意:样式对象里面的键名并不是 CSS 中的写法(font-size要写成fontSize),而是遵循 JavaScript 对象属性的 camelCase 规则。
CSSModules => styled
CSS Modules 需要为每个节点手工维护styles.xxx类名引用;迁移到 styled-components 后,样式与组件合并为一个声明,去掉了类名桥接层。下面的计数器组件是两种写法的等效对照。
CSS Modules 写法:
import React, { useState } from 'react'; import styles from './styles.css'; function ExampleCounter() { const [count, setCount] = useState(0) return ( <div className={styles.counter}> <p className={styles.paragraph}> {count} </p> <button className={styles.button} onClick={() => setCount(count +1)} > + </button> <button className={styles.button} onClick={() => setCount(count -1)} > - </button> </div> ); }与下面 styled 写法等效
import styled from 'styled-components'; const StyledCounter = styled.div` /* ... */ `; const Paragraph = styled.p` /* ... */ `; const Button = styled.button` /* ... */ `; function ExampleCounter() { const [count, setCount] = useState(0); const increment = () => { setCount(count +1); } const decrement = () => { setCount(count -1); } return ( <StyledCounter> <Paragraph>{count}</Paragraph> <Button onClick={increment}> + </Button> <Button onClick={decrement}> - </Button> </StyledCounter> ); }两种方案产出的 DOM 结构完全一致,styled 版本把"选择器 + 样式"收敛进了组件本身。
伪元素、伪选择器和嵌套
styled-components 内置了类似 Sass 的嵌套语法,&表示当前组件自身的选择器,可组合出各种伪类与上下文选择器:
const Thing = styled.div.attrs((/* props */) => ({ tabIndex: 0 }))` color: blue; &:hover { /* <Thing> 悬停时 */ color: red; } & ~ & { /* <Thing> 作为 <Thing> 的兄弟,但可能不直接在它旁边 */ background: tomato; } & + & { /* <Thing> 旁边的 <Thing> */ background: lime; } &.something { /* <Thing> 标记有一个额外的 CSS 类 ".something" */ background: orange; } .something-else & { /* <Thing> 在另一个标记为 ".something-else" 的元素中 */ border: 1px solid; } `; render( <React.Fragment> <Thing>Hello world!</Thing> <Thing>你怎么样?</Thing> <Thing className="something"> 艳阳高照... </Thing> <div>今天真是美好的一天。</div> <Thing>你不觉得吗?</Thing> <div className="something-else"> <Thing>灿烂</Thing> </div> </React.Fragment> );各选择器含义归纳:
| 选择器写法 | 作用 |
|---|---|
&:hover | 组件自身悬停时 |
& ~ & | 作为另一个 Thing 的兄弟节点(不一定相邻) |
& + & | 紧邻另一个 Thing 的兄弟节点 |
&.something | 组件同时带有额外类.something |
.something-else & | 组件位于带.something-else类的祖先元素内部 |
改变 styled 组件样式
在插值函数里通过css助手与&&(双&)组合出"仅针对当前组件"的高优先级选择器,实现引用其他 styled 组件并精准覆盖其样式:
import { css } from 'styled-components' import styled from 'styled-components' const Input = styled.input.attrs({ type: "checkbox" })``; const LabelText = styled.span` ${(props) => { switch (props.$mode) { case "dark": return css` color: white; ${Input}:checked + && { color: blue; } `; default: return css` color: black; ${Input}:checked + && { color: red; } `; } }} `; function Example() { return ( <React.Fragment> <Label> <Input defaultChecked /> <LabelText>Foo</LabelText> </Label> <Label> <Input /> <LabelText $mode="dark"> Foo </LabelText> </Label> </React.Fragment> ); }${Input}会在选择器中展开为 Input 组件的类名,&&则会重复当前组件类名以提升特异性,从而覆盖来自其他位置的同类规则。
全局样式 createGlobalStyle
与组件级样式不同,createGlobalStyle用于注入全局样式(如 reset、字体、主题变量)。它渲染时不产生任何 DOM 节点,只把样式注入全局:
import { styled, createGlobalStyle } from 'styled-components' const Thing = styled.div` && { color: blue; } `; const GlobalStyle = createGlobalStyle` div${Thing} { color: red; } `; const Example = () => ( <React.Fragment> <GlobalStyle /> <Thing> 我是蓝色的 </Thing> </React.Fragment> );div${Thing}表示"包含了 Thing 类名的 div"选择器。由于组件自身&&的特异性更高,<Thing>仍显示为蓝色。
className 使用
styled 组件的样式内也可以嵌套普通类选择器,用来给子元素(如 label)施加样式,无需为该子元素单独创建 styled 组件:
const Thing = styled.div` color: blue; /* <Thing> 中标记为".something"的元素 */ .something { border: 1px solid; } `; function Example() { return ( <Thing> <label htmlFor="foo-button" className="something" > 神秘按钮 </label> <button id="foo-button"> 我该怎么办? </button> </Thing> ) }当组件需要接收外部className时,styled 组件会自动把外部类与生成类合并到根元素上,因此这里的className="something"能命中嵌套规则。
共享样式片段
当一段样式需要跨组件复用,或需要把关键帧等动态值拼进模板时,必须使用css助手包裹,而不是普通字符串拼接:
const rotate = keyframes` from {top:0px;} to {top:200px;} `; // ❌ 这将引发错误! const styles = ` animation: ${rotate} 2s linear infinite; `; // ✅ 这将按预期工作 const styles = css` animation: ${rotate} 2s linear infinite; `;原因:模板字符串会把rotate强制转成字符串,破坏关键帧对象引用;css助手会保留插值结构,交给编译器做正确的解析与去重。
Class 组件样式定义
class 组件必须把this.props.className渲染到实际的 DOM 节点上,才能被 styled 化并接收外部样式:
class NewHeader extends React.Component { render() { return ( <div className={this.props.className} /> ); } } const StyledA = styled(NewHeader)`` const Box = styled.div` ${StyledA} { /* 变更 NewHeader 样式 */ } `;styled(NewHeader)`` 创建出可被引用的StyledA,随后在Box内通过${StyledA}` 选择器对它做定向样式变更。
附加额外的 Props
attrs用于给组件预设(静态或动态计算的)props,被预设的 props 会自动应用到 DOM 节点上,并且可以在样式插值中直接使用:
const Input = styled.input.attrs(props=>({ // 我们可以定义静态道具 type: "text", // 或者我们可以定义动态的 size: props.size || "1em", }))` color: palevioletred; font-size: 1em; border: 2px solid palevioletred; border-radius: 3px; /* 这里我们使用动态计算的 props */ margin: ${props => props.size}; padding: ${props => props.size}; `;使用Input组件:
function Example() { return ( <div> <Input placeholder="小文本输入" /> <br /> <Input placeholder="更大的文本输入" size="2em" /> </div> ) }未传size时默认1em,传入size="2em"时边距随之放大,同时type始终被预设为text。
覆盖 .attrs
对已带attrs的组件继续调用.attrs,后者的预设会覆盖前者,且预设的 props 可以继续在派生组件里使用:
const Input = styled.input.attrs(props=>({ type: "text", size: props.size || "1em", }))` border: 2px solid palevioletred; margin: ${props => props.size}; padding: ${props => props.size}; `; // Input 的attrs会先被应用,然后这个 attrs obj const PasswordInput = styled(Input).attrs({ type: "password", })` /* 同样,border 将覆盖 Input 的边框 */ border: 2px solid aqua; `;使用Input和PasswordInput组件:
render( <div> <Input placeholder="更大的文本输入" size="2em" /> <br /> {/*⚠️ 仍然可以使用Input中的 size attr*/} <PasswordInput placeholder="更大的密码输入" size="2em" /> </div> );PasswordInput的type被覆盖为password,但依然继承并使用Input定义的size动态预设。
动画
通过keyframes定义关键帧,再在组件样式中通过插值引用:
创建关键帧:
const rotate = keyframes` from { transform: rotate(0deg); } to { transform: rotate(360deg); } `;创建一个Rotate组件:
// 它将在两秒内旋转我们传递的所有内容 const Rotate = styled.div` display: inline-block; animation: ${rotate} 2s linear infinite; padding: 2rem 1rem; font-size: 1.2rem; `;使用Rotate组件:
function Example() { return ( <Rotate>< 💅🏾 ></Rotate> ) }keyframes返回的对象同样需要像css一样通过插值嵌入模板(不能字符串拼接),styled-components 会自动生成唯一动画名并注入@keyframes规则。
isStyledComponent
当面对一个"可能是 styled 组件"的模块时,用isStyledComponent做运行时判断,决定是直接使用还是包装成 styled 组件:
import React from 'react' import styled, { isStyledComponent } from 'styled-components' import MaybeStyledComponent from './my' let TargetedComponent = isStyledComponent(MaybeStyledComponent) ? MaybeStyledComponent : styled(MaybeStyledComponent)``; const ParentComponent = styled.div` color: cornflowerblue; ${TargetedComponent} { color: tomato; } `;这段代码保证了TargetedComponent一定是一个 styled 组件,从而可以在${TargetedComponent}选择器中安全引用。
ThemeConsumer
不通过组件样式访问主题,而是直接在渲染函数中消费主题值:
import { ThemeConsumer } from 'styled-components' function Example() { return ( <ThemeConsumer> {theme => ( <div>主题色是 {theme.color}</div> )} </ThemeConsumer> ); }ThemeConsumer使用 render props 模式,把当前主题对象作为参数传给子函数。
TypeScript
安装
Web 应用上安装类型定义:
npm install -D @types/styled-componentsReact Native 应用上安装类型定义:
npm install -D \ @types/styled-components \ @types/styled-components-react-native如果对 TypeScript 不熟悉,可以参考本仓库的 TypeScript 备忘清单。
自定义 Props
通过泛型参数为 styled 组件声明 props 类型,插值函数中的props即获得类型推导:
import styled from 'styled-components'; interface TitleProps { readonly isActive: boolean; } const Title = styled.h1<TitleProps>` color: ${(props) => ( props.isActive ? props.theme.colors.main : props.theme.colors.secondary )}; `;props.theme的类型由 ThemeProvider 注入的主题对象推导,isActive则由TitleProps声明,二者都获得完整的编译期检查。
简单的 Props 类型定义
针对扩展已有组件的场景,同样可以用泛型声明新增 props:
import styled from 'styled-components'; import Header from './Header'; const Header = styled.header` font-size: 12px; `; const NewHeader = styled(Header)<{ customColor: string; }>` color: ${(props) => props.customColor}; `;NewHeader在继承Header样式的基础上,新增了必填的customColor字符串属性。
禁止转移到子组件($)
默认情况下,传给 styled 组件的非 HTML 原生属性会被透传到真实 DOM。若不想让自定义属性出现在 DOM 上,可在属性名前加美元符号$,styled-components 会识别并阻止其转移到子组件:
import styled from 'styled-components'; import Header from './Header'; interface ReHeader { $customColor: string; } const ReHeader = styled(Header)<ReHeader>` color: ${ props => props.$customColor }; `;禁止customColor属性转移到Header组件,在其前面加上美元($)符号即可。$前缀是 v5 起推荐的"瞬态 prop"(transient prop)约定,既满足样式计算需求,又避免污染 DOM 属性(如出现customcolor="..."之类的非法属性警告)。
函数组件类型继承
用 React 内置的 HTML 属性类型(DetailedHTMLProps、ImgHTMLAttributes)扩展出自定义组件 props,再封装为带完整类型的高阶组件:
import { FC, PropsWithRef, DetailedHTMLProps, ImgHTMLAttributes } from 'react'; import styled from 'styled-components'; const Img = styled.img` height: 32px; width: 32px; `; export interface ImageProps extends DetailedHTMLProps< ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement > { text?: string; }; export const Image: FC<PropsWithRef<ImageProps>> = (props) => ( <Img src="" alt="" {...props} /> );ImageProps继承原生<img>的全部属性,并追加可选的自定义text字段;通过{...props}展开后,所有合法属性都会被透传。
React Native
基础实例
在 React Native 中,从styled-components/native导入即可使用styled.View、styled.Text等内建组件工厂:
import React from 'react' import styled from 'styled-components/native' const StyledView = styled.View` background-color: papayawhip; `; const StyledText = styled.Text` color: palevioletred; `; class MyReactNativeComponent extends React.Component { render() { return ( <StyledView> <StyledText>Hello World!</StyledText> </StyledView> ); } }与 Web 版 API 完全一致,只是目标组件来自 React Native 而非 DOM 标签。
React Native 中写 CSS
React Native 样式遵循 RN 的样式子集,可写transform、text-shadow-offset、font-variant等 RN 支持属性:
import styled from 'styled-components/native' const RotatedBox = styled.View` transform: rotate(90deg); text-shadow-offset: 10px 5px; font-variant: small-caps; margin: 5px 7px 2px; `; function Example() { return ( <RotatedBox /> ) }与 web 版本的区别:不能使用keyframes和createGlobalStyle助手,因为 React Native 不支持关键帧或全局样式。如果使用媒体查询或嵌套 CSS,会收到警告。
高级用法
主题化
ThemeProvider通过 React Context 向下层组件注入主题对象,样式插值函数通过props.theme消费:
import styled, { ThemeProvider } from 'styled-components' // 定义我们的按钮,但这次使用 props.theme const Button = styled.button` font-size: 1em; margin: 1em; padding: 0.25em 1em; border-radius: 3px; /* 使用 theme.main 为边框和文本着色 */ color: ${props => props.theme.main}; border: 2px solid ${props => props.theme.main}; `; // 我们正在为未包装在 ThemeProvider 中的按钮传递默认主题 Button.defaultProps = { theme: { main: "palevioletred" } } // 定义 props.theme 的外观 const theme = { main: "mediumseagreen" }; render( <div> <Button>Normal</Button> <ThemeProvider theme={theme}> <Button>Themed</Button> </ThemeProvider> </div> );位于ThemeProvider之外的按钮读取defaultProps提供的默认主题,位于其内部的按钮则读取注入的mediumseagreen主题。
功能主题
ThemeProvider的theme除了可以是对象,还可以是接收外层主题并返回新主题的函数,实现主题的派生与反转:
import styled, { ThemeProvider } from 'styled-components' // 定义我们的按钮,但这次使用 props.theme const Button = styled.button` color: ${props => props.theme.fg}; border: 2px solid ${props => props.theme.fg}; background: ${props => props.theme.bg}; font-size: 1em; margin: 1em; padding: 0.25em 1em; border-radius: 3px; `; // 在主题上定义我们的`fg`和`bg` const theme = { fg: "palevioletred", bg: "white" }; // 这个主题交换了`fg`和`bg` const invertTheme = ({ fg, bg }) => ({ fg: bg, bg: fg }); render( <ThemeProvider theme={theme}> <div> <Button>默认主题</Button> <ThemeProvider theme={invertTheme}> <Button>反转主题</Button> </ThemeProvider> </div> </ThemeProvider> );内层ThemeProvider把函数invertTheme应用于外层主题,得到前景/背景互换的新主题,嵌套 Provider 支持任意层级的主题覆盖。
通过 withTheme 高阶组件
class 组件无法直接使用 hooks,可通过withTheme高阶组件把当前主题作为props.theme注入:
import { withTheme } from 'styled-components' class MyComponent extends React.Component { render() { console.log('Current theme: ', this.props.theme) // ... } } export default withTheme(MyComponent)useContext 钩子
函数组件可以直接使用 React 的useContext消费 styled-components 导出的ThemeContext:
import { useContext } from 'react' import { ThemeContext } from 'styled-components' const MyComponent = () => { const themeContext = useContext(ThemeContext) console.log('Current theme: ', themeContext) // ... }useTheme 自定义钩子
styled-components 提供了封装好的useTheme钩子,是函数组件读取主题最简洁的方式:
import {useTheme} from 'styled-components' const MyComponent = () => { const theme = useTheme() console.log('Current theme: ', theme) // ... }主题 props
主题可以按"就近覆盖"的粒度应用:单个组件可通过theme属性直接传入主题,覆盖 Provider 层级的主题值:
import { ThemeProvider, styled } from 'styled-components'; // 定义我们的按钮 const Button = styled.button` font-size: 1em; margin: 1em; padding: 0.25em 1em; /* 使用 theme.main 为边框和文本着色 */ color: ${props => props.theme.main}; border: 2px solid ${props => props.theme.main}; `; // 定义主题的外观 const theme = { main: "mediumseagreen" };使用自定义主题组件:
render( <div> <Button theme={{ main: "royalblue" }}> 特设主题 </Button> <ThemeProvider theme={theme}> <div> <Button>Themed</Button> <Button theme={{ main: "darkorange" }} > 被覆盖 </Button> </div> </ThemeProvider> </div> );直接传theme的组件优先级最高:royalblue应用于无 Provider 的按钮,darkorange覆盖了 Provider 注入的mediumseagreen。
Refs
styled 组件照常转发ref(React 16.3+ 的 createRef 或函数 ref),可用来做聚焦等命令式操作:
import { ThemeProvider, styled } from 'styled-components'; const Input = styled.input` border: none; border-radius: 3px; `; class Form extends React.Component { constructor(props) { super(props); this.inputRef = React.createRef(); } render() { return ( <Input ref={this.inputRef} placeholder="Hover to focus!" onMouseEnter={() => { this.inputRef.current.focus() }} /> ); } }使用Form组件:
function Example() { return ( <Form /> ) }鼠标移入输入框时,onMouseEnter触发this.inputRef.current.focus(),实现悬停聚焦。
特异性问题
styled 组件生成的类选择器通常带有较高特异性,外部普通类名难以覆盖。假设在文件MyComponent.js中定义组件:
const MyComponent = styled.div` background-color: green; `;定义样式my-component.css:
.red-bg { background-color: red; }使用MyComponent组件:
<MyComponent className="red-bg" />由于某种原因,这个组件仍然有绿色背景,即使你试图用red-bg类覆盖它!
解决方案
提升覆盖规则的特异性,将类名重复一次:
.red-bg.red-bg { background-color: red; }.red-bg.red-bg的双类名特异性高于单个类名,即可稳定覆盖 styled 组件生成的样式。
ThemeProvider
最基础的 Provider 用法:theme属性直接传对象,被包裹组件的props.theme即可读取:
import styled, { ThemeProvider } from 'styled-components' const Box = styled.div` color: ${props => props.theme.color}; `; const Example = () => ( <ThemeProvider theme={{ color: 'mediumseagreen' }}> <Box>I'm mediumseagreen!</Box> </ThemeProvider> );shouldForwardProp
默认情况下 styled 组件会把所有非 HTML 属性透传给 DOM。用.withConfig({ shouldForwardProp })可以自定义"哪些 props 应当被透传",配合defaultValidatorFn保留框架默认校验逻辑:
const Comp = styled('div').withConfig({ shouldForwardProp: (prop, defaultValidatorFn) => !['hidden'].includes(prop) && defaultValidatorFn(prop), }).attrs({ className: 'foo' })` color: red; &.foo { text-decoration: underline; } `; const Example = () => ( <Comp hidden draggable="true"> Drag Me! </Comp> );示例中拦截了hidden属性,使其不落到 DOM 上,同时保留 React 合法的draggable等属性正常透传;attrs预设的foo类配合&.foo选择器完成下划线装饰。
速查要点回顾
- 创建组件:
styled.h1、styled(Component)标签模板,样式即组件。 - 动态样式:模板插值函数接收
props,支持条件样式、传入值与主题消费。 - 复用与覆盖:
styled(Button)继承扩展;as切换标签或自定义组件;&&提升特异性精准覆盖。 - attrs:预设静态/动态 props,派生组件可继续覆盖。
- 主题体系:
ThemeProvider(对象或函数)、ThemeConsumer、withTheme、useTheme、ThemeContext、组件级theme就近覆盖。 - TypeScript:泛型声明 props、
$前缀瞬态 prop、基于DetailedHTMLProps的类型继承。 - React Native:从
styled-components/native导入,不支持keyframes与createGlobalStyle。 - 注意事项:styled 组件必须在 render 之外定义;共享片段用
css;覆盖外部样式需提升特异性(.red-bg.red-bg)。
本清单完整收录于仓库 docs/styled-components.md,该文件与本仓库其他数百份速查表一样,统一通过refs-cli构建为可检索的 HTML 速查站(构建脚本见 package.json 的build与start命令),可在浏览器中随查随用。
- 文档
- 知识库
- 教程
- 开发工具
【免费下载链接】reference
为开发人员分享快速参考备忘清单(速查表)
相关推荐
styled-components 完整实战指南:Reference 速查清单中的 CSS-in-JS 组件样式方案
styled components 完整实战指南:Reference 速查清单中的 CSS in JS 组件样式方案 本文以本仓库 styled compone
文档教程styled-components在React-Boilerplate中的应用:CSS-in-JS实战指南
styled components在React Boilerplate中的应用:CSS in JS实战指南 styled components是React生态中
前端示例工程开发工具spin.js中的CSS-in-JS:使用styled-components集成
spin.js中的CSS in JS:使用styled components集成 在现代前端开发中,CSS in JS方案已经成为组件化样式管理的主流选择。本文
UI组件前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考