styled
这是默认导出。这是一个我们用来创建 styled.tagname
帮助器方法的底层工厂。
参数 | 描述 |
---|---|
| 一个有效的 React 组件或一个像 |
返回一个接受标记模板字面量并将其转换为 StyledComponent
的函数。
您可以在 入门 部分中看到此方法的介绍。
TaggedTemplateLiteral
这就是您传递到 styled 调用中的内容 - 一个标记模板字面量。这是一个 ES6 语言特性。您可以在 标记模板字面量 部分中了解更多信息。
输入 | 描述 |
---|---|
规则 | 任何 CSS 规则(字符串) |
插值 | 这可以是字符串或函数。字符串将按原样与规则合并。函数将接收 styled 组件的 props 作为第一个也是唯一的参数。 |
有关如何根据 props 调整样式的更多信息,请阅读 根据 props 调整 部分。
传递到插值函数中的属性会附加一个特殊属性 theme
,该属性由更高层的 ThemeProvider
组件注入。查看关于 主题 的部分,以获取有关此内容的更多信息。
✨ Magic
您也可以从插值中返回对象或直接输入对象,它们将被视为内联样式。但是,强烈建议不要这样做,因为 CSS 语法支持伪选择器、媒体查询、嵌套等,而对象语法不支持这些。
StyledComponent
一个 styled React 组件。当您使用样式调用 styled.tagname
或 styled(Component)
时,将返回此组件。
此组件可以接受任何 prop。如果它是有效的属性,它会将其传递到 HTML 节点,否则它只会将其传递到插值函数中。(见 标记模板字面量)
您可以毫无问题地将任意类名传递给 styled 组件,它将与 styled 调用定义的样式并排应用。(例如 <MyStyledComp className="bootstrap__btn" />
)
这是一个可链接的方法,它将一些 props 附加到 styled 组件。第一个也是唯一的参数是一个将与组件剩余 props 合并的对象。attrs
对象接受以下值
值 | 描述 |
---|---|
Prop 值 | 这些可以是任何类型,除了函数。它们将保持静态并将与现有组件 props 合并。 |
Prop 工厂 | 一个接收传递给组件的 props 并计算一个值,然后该值将与现有组件 props 合并的函数。 |
返回另一个 StyledComponent
。
在 附加额外 props 部分了解更多有关此构造函数的信息。
"as"
多态 prop如果您想保留应用于组件的所有样式,但只切换最终呈现的内容(无论是不同的 HTML 标签还是不同的自定义组件),您可以在运行时使用 "as"
prop 来完成此操作。
这种方法在导航栏等用例中非常有用,其中某些项目应该是链接,而某些项目只是按钮,但所有项目都具有相同的样式。
如果您选择使用还接受 "as"
prop 的 styled()
HOC 包装另一个组件,请使用 "forwardedAs"
将所需的 prop 传递给包装的组件。
如果您想阻止旨在由 styled 组件使用的 props 传递给底层 React 节点或渲染到 DOM 元素,您可以将 prop 名称加一个美元符号 ($
),将其转换为瞬态 prop。
在此示例中,$draggable
不会像 draggable
那样渲染到 DOM。
Drag me!
这是一种比瞬态 props 更动态、更细粒度的过滤机制。在多个高阶组件组合在一起并恰好共享相同 prop 名称的情况下,它非常方便。shouldForwardProp
的工作方式与 Array.filter
的谓词回调类似。一个未通过测试的 prop 不会像瞬态 prop 那样传递给底层组件。
请记住,正如在此示例中一样,其他可链接方法应始终在 .withConfig
之后执行。
Drag Me!
可选地,shouldForwardProp
可以接受第二个参数,该参数提供对默认验证器函数的访问。此函数可以用作后备,当然,它也像谓词一样工作,根据已知的 HTML 属性进行过滤。
ThemeProvider
用于主题的帮助器组件。通过上下文 API 将主题注入到组件树中它下面的所有 styled 组件中。查看关于 主题 的部分。
Props | 描述 |
---|---|
theme | 一个对象(或返回对象的函数),它将作为 |
简单用法
I'm mediumseagreen!
使用嵌套的 ThemeProvider
添加或替换外部主题
I'm mediumseagreen with a white background!I'm mediumseagreen with a black background!
css
prop有时您不想只创建一个额外的组件来应用一点样式。css
prop 是一种方便的方法,可以在不确定固定组件边界的情况下对组件进行迭代。它适用于普通 HTML 标签和组件,并支持任何 styled 组件支持的所有内容,包括根据 props 调整、主题和自定义组件。
要启用对 css
prop 的支持,您必须使用 Babel 插件。
<div css={` background: papayawhip; color: ${props => props.theme.colors.text}; `} /> <Button css="padding: 0.5em 1em;" />
在幕后,Babel 插件会将任何带有 css
prop 的元素转换为 styled 组件。例如,上面的代码变成
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 />
注意,您甚至不必添加导入,Babel 插件会自动完成!(除非您使用 Babel 宏,请参阅下文)
由于缺乏使用情况和对其他用户来说不必要的膨胀,此功能在 v6.1 中被移除。 更多信息
您可以在 create-react-app
中使用 Babel 宏 使其工作。不幸的是,Babel 宏仅在导入时运行,因此 **导入无法自动添加**。如果您手动将导入添加到宏,上面的代码将完美运行
import styled from 'styled-components/macro' <div css={` background: papayawhip; color: ${props => props.theme.colors.text}; `} /> <Button css="padding: 0.5em 1em;" />
为了防止 TypeScript 在任意元素的 css
属性上出现错误,请安装 @types/styled-components
并在您的项目中添加以下导入
import {} from 'styled-components/cssprop'
请参阅 https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31245#issuecomment-446011384 以获取更多信息。
如果您使用的是高于 v6 的版本,则无需安装 @types/styled-components
。相反,您可以直接在您的项目中导入 CSSProp
,如下所示
import {} from 'react' import type { CSSProp } from 'styled-components' declare module 'react' { interface Attributes { css?: CSSProp | undefined } }
createGlobalStyle
一个辅助函数,用于生成一个特殊的 StyledComponent
,它处理全局样式。通常,样式化组件会自动作用域到本地 CSS 类,因此与其他组件隔离。在 createGlobalStyle
的情况下,此限制被移除,并且可以应用诸如 CSS 重置或基本样式表之类的内容。
参数 | 描述 |
---|---|
| 一个标记模板字面量,包含您的 CSS 和插值。 |
返回一个 StyledComponent
,它不接受子元素。将其放置在 React 树的顶部,全局样式将在组件“渲染”时注入。
import { createGlobalStyle } from 'styled-components' const GlobalStyle = createGlobalStyle<{ $whiteColor?: boolean; }>` body { color: ${props => (props.$whiteColor ? 'white' : 'black')}; } ` // later in your app <React.Fragment> <GlobalStyle $whiteColor /> <Navigation /> {/* example of other top-level stuff */} </React.Fragment>
由于 GlobalStyle
组件是一个 StyledComponent
,这意味着它也可以访问来自 <ThemeProvider>
组件 的主题,如果提供的话。
import { createGlobalStyle, ThemeProvider } from 'styled-components' const GlobalStyle = createGlobalStyle<{ $whiteColor?: boolean; }>` body { color: ${props => (props.$whiteColor ? 'white' : 'black')}; font-family: ${props => props.theme.fontFamily}; } ` // later in your app <ThemeProvider theme={{ fontFamily: 'Helvetica Neue' }}> <React.Fragment> <Navigation /> {/* example of other top-level stuff */} <GlobalStyle $whiteColor /> </React.Fragment> </ThemeProvider>
css
一个辅助函数,用于从包含插值的模板字面量生成 CSS。如果您在插值中返回一个包含函数的模板字面量,则需要使用它,因为 JavaScript 中的标记模板字面量的使用方法。
如果您正在插值一个字符串,则无需使用它,只有在插值一个函数时才需要使用它。
参数 | 描述 |
---|---|
| 一个标记模板字面量,包含您的 CSS 和插值。 |
返回一个插值数组,它是一个扁平化的数据结构,您可以将其作为插值本身传递。
import styled, { css } from 'styled-components' interface ComponentProps { $complex?: boolean; $whiteColor?: boolean; } const complexMixin = css<ComponentProps>` color: ${props => (props.$whiteColor ? 'white' : 'black')}; ` const StyledComp = styled.div<ComponentProps>` /* This is an example of a nested interpolation */ ${props => (props.$complex ? complexMixin : 'color: blue;')}; `
如果您省略 css,您的函数将被 toString()
处理,您将不会获得预期的结果。
keyframes
一个辅助方法,用于为动画创建关键帧。
参数 | 描述 |
---|---|
| 一个标记模板字面量,包含您的关键帧。 |
返回一个 Keyframes 模型,用于在动画声明中使用。如果您希望获取生成的动画名称,可以使用返回模型上的 getName()
API。
在 styled-components v3 及更低版本中,keyframes
辅助函数直接返回动画名称,而不是包含 getName
方法的对象。
import styled, { keyframes } from 'styled-components' const fadeIn = keyframes` 0% { opacity: 0; } 100% { opacity: 1; } ` const FadeInButton = styled.button` animation: 1s ${fadeIn} ease-out; `
如果您将样式规则作为部分进行组合,请确保使用 css
辅助函数。
import styled, { css, keyframes } from 'styled-components' interface AnimationProps { $animationLength: number; } const pulse = keyframes` 0% { opacity: 0; } 100% { opacity: 1; } ` const animation = props => css<AnimationProps>` ${pulse} ${props.$animationLength} infinite alternate; ` const PulseButton = styled.button<AnimationProps>` animation: ${animation}; `
您可以在 动画 部分了解更多关于在 styled-components 中使用动画的信息。
StyleSheetManager
一个辅助组件,用于修改样式的处理方式。对于涉及样式化组件的给定子树,您可以自定义各种行为,例如 CSS 运行时处理器(stylis)如何通过用户端插件和选项覆盖来处理样式。
Props | 描述 |
---|---|
disableCSSOMInjection (v5+) | 切换到较慢的基于文本节点的 CSS 注入系统,用于将样式添加到 DOM。对于与尚未升级以从 CSSOM API 使用样式的第三方工具集成很有用。 |
disableVendorPrefixes (v5,在 v6 中移除) | 将给定子树排除在为渲染的组件添加遗留 CSS 属性之外。 |
enableVendorPrefixes (v6+) | 将给定子树选择为为渲染的组件添加遗留 CSS 属性。 |
sheet | 前方有龙。如果需要,请创建并提供您自己的 StyleSheet,以用于高级 SSR 场景。 |
stylisPlugins (v5+) | 编译期间由 stylis 运行的插件数组。查看 npm 上有什么 . |
target | 前方有龙。提供一个备用 DOM 节点以注入样式信息。 |
例如,如果您的应用程序适用于遗留浏览器,您可能希望为您的样式启用供应商前缀
If you inspect me, there are vendor prefixes for the flexbox style.
另一个例子是通过用户端 stylis-plugin-rtl
插件为您的样式启用从右到左的翻译
My border is now on the right!
isStyledComponent
一个帮助识别样式化组件的实用程序。
参数 | 描述 |
---|---|
| 任何可能被认为是样式化组件或包裹在样式化组件中的 React 组件的函数 |
如果传递的函数是有效的样式化组件包裹的组件类,则返回 true。它可以用来确定组件是否需要包裹,以便它可以用作组件选择器
import React from 'react' import styled, { isStyledComponent } from 'styled-components' import MaybeStyledComponent from './somewhere-else' let TargetedComponent = isStyledComponent(MaybeStyledComponent) ? MaybeStyledComponent : styled(MaybeStyledComponent)`` const ParentComponent = styled.div` color: royalblue; ${TargetedComponent} { color: tomato; } `
withTheme
这是一个高级组件工厂,用于从 ThemeProvider
获取当前主题,并将其作为 theme
属性传递给您的组件。
参数 | 描述 |
---|---|
| 任何可以处理 |
将传递的组件包装在包装器(高级组件)中返回。传递的组件将收到一个 theme
属性,其中包含当前主题对象。
import { withTheme } from 'styled-components' class MyComponent extends React.Component { render() { console.log('Current theme: ', this.props.theme) // ... } } export default withTheme(MyComponent)
所有样式化组件 自动接收主题作为属性,因此只有在您希望出于其他原因访问主题时,才需要这样做。
useTheme
这是一个自定义钩子,用于从 ThemeProvider
获取当前主题。
import { useTheme } from 'styled-components' function MyComponent() { const theme = useTheme() console.log('Current theme: ', theme) // ... }
所有样式化组件 自动接收主题作为属性,因此只有在您希望出于其他原因访问主题时,才需要这样做。
ThemeConsumer
这是由 React.createContext
创建的 "消费者" 组件,作为 ThemeProvider
的配套组件。它使用 渲染属性模式 允许在渲染期间动态访问主题。
它将当前主题(基于您组件树中更高位置的 ThemeProvider
)作为参数传递给子函数。从这个函数中,您可以返回更多 JSX 或不返回任何内容。
import { ThemeConsumer } from 'styled-components' export default class MyComponent extends React.Component { render() { return ( <ThemeConsumer> {theme => <div>The theme color is {theme.color}.</div>} </ThemeConsumer> ) } }
所有样式化组件 自动接收主题作为属性,因此只有在您希望出于其他原因访问主题时,才需要这样做。
find
一个便利方法,用于在给定的 DOM 根节点中查找样式化组件渲染的 DOM 节点的单个实例。
import styled from 'styled-components' import { find } from 'styled-components/test-utils' const Foo = styled.div` color: red; ` /** * Somewhere in your app: * * ReactDOM.render( * <main> * <Foo /> * </main>, document.body * ); */ // retrieves the first instance of "Foo" in the body (querySelector under the hood) find(document.body, Foo) // HTMLDivElement | null
findAll
一个便利方法,用于在给定的 DOM 根节点中查找样式化组件渲染的 DOM 节点的所有实例。
import styled from 'styled-components' import { findAll } from 'styled-components/test-utils' const Foo = styled.div` color: ${props => props.color}; ` /** * Somewhere in your app: * * ReactDOM.render( * <main> * <Foo color="red" /> * <Foo color="green" /> * </main>, document.body * ); */ // retrieves a NodeList of instances of "Foo" in the body (querySelectorAll under the hood) findAll(document.body, Foo) // NodeList<HTMLDivElement> | null
enzymeFind
一个便利方法,用于在 enzyme 包装器中查找特定样式化组件的实例。
import { mount } from 'enzyme' import styled from 'styled-components' import { enzymeFind } from 'styled-components/test-utils' const Foo = styled.div` color: red; ` const wrapper = mount( <div> <Foo>bar</Foo> </div> ) enzymeFind(wrapper, Foo)
在样式化组件中,我们支持所有 CSS 以及嵌套。由于我们生成的是实际的样式表,而不是内联样式,因此在 CSS 中起作用的东西在 styled-components 中也能起作用!
Hello World!
与符号 (&
) 将被我们为该样式化组件生成的唯一类名替换,从而使复杂的逻辑变得容易。
styled-components 提供 TypeScript 定义,这增强了 IDE 中的编辑体验,并提高了 TypeScript 项目的类型安全性。
对于较旧版本的 styled-components,可以通过 @types/styled-components
NPM 包获得社区定义。
自定义文件的 v4.1.4
版本起,可以通过使用 声明合并 扩展 styled-components 的 TypeScript 定义。
因此,第一步是创建一个声明文件。例如,我们将其命名为 styled.d.ts
。
// import original module declarations import 'styled-components'; // and extend them! declare module 'styled-components' { export interface DefaultTheme { borderRadius: string; colors: { main: string; secondary: string; }; } }
React-Native
import 'styled-components/native' declare module 'styled-components/native' { export interface DefaultTheme { borderRadius: string; colors: { main: string; secondary: string; }; } }
DefaultTheme
默认用作 props.theme
的接口。默认情况下,接口 DefaultTheme
是空的,这就是为什么我们需要扩展它的原因。
现在我们可以使用上面步骤中声明的 DefaultTheme
来创建主题。
// my-theme.ts import { DefaultTheme } from 'styled-components'; const myTheme: DefaultTheme = { borderRadius: '5px', colors: { main: 'cyan', secondary: 'magenta', }, }; export { myTheme };
就这样!我们只需要使用任何原始导入就可以使用 styled-components。
import styled, { createGlobalStyle, css } from 'styled-components'; // theme is now fully typed export const MyComponent = styled.div` color: ${props => props.theme.colors.main}; `; // theme is also fully typed export MyGlobalStyle = createGlobalStyle` body { background-color: ${props => props.theme.colors.secondary}; } `; // and this theme is fully typed as well export cssHelper = css` border: 1px solid ${props => props.theme.borderRadius}; `;
如果你要 根据 props 调整样式,并且这些 props 不属于基本标签/组件 props,你可以使用类型参数告诉 TypeScript 这些额外的自定义 props 是什么,例如这样(TypeScript v2.9+
是必需的)。
import styled from 'styled-components'; import Header from './Header'; interface TitleProps { readonly $isActive: boolean; } const Title = styled.h1<TitleProps>` color: ${(props) => (props.$isActive ? props.theme.colors.main : props.theme.colors.secondary)}; `;
注意:如果你为一个标准标签(例如上面示例中的 <h1>
)设置样式,styled-components 不会传递自定义 props(以避免 未知 Prop 警告)。
但是,它会将所有 props 传递给自定义 React 组件。
import styled from 'styled-components'; import Header from './Header'; const NewHeader = styled(Header)<{ customColor: string }>` color: ${(props) => props.customColor}; `; // Header will also receive props.customColor
如果 customColor 属性不应该传递给 Header 组件,你可以利用 瞬态 props,通过在它前面加上一个美元符号 ($) 来实现。
import styled from 'styled-components'; import Header from './Header'; const NewHeader2 = styled(Header)<{ $customColor: string }>` color: ${(props) => props.$customColor}; `; // Header does NOT receive props.$customColor
根据你的使用场景,你可以通过自己提取自定义 props 来实现类似的结果。
import styled from 'styled-components'; import Header, { Props as HeaderProps } from './Header'; const NewHeader3 = styled(({ customColor, ...rest }: { customColor: string } & HeaderProps) => <Header {...rest} />)` color: ${(props) => props.customColor}; `;
或者使用 shouldForwardProp
import styled from 'styled-components'; import Header from './Header'; const NewHeader4 = styled(Header).withConfig({ shouldForwardProp: (prop) => !['customColor'].includes(prop), })<{ customColor: string }>` color: ${(props) => props.customColor}; `;
className
的警告定义组件时,你需要在 Props 接口中将 className
标记为可选的。
interface LogoProps { /* This prop is optional, since TypeScript won't know that it's passed by the wrapper */ className?: string; } class Logo extends React.Component<LogoProps, {}> { render() { return <div className={this.props.className}>Logo</div>; } } const LogoStyled = styled(Logo)` font-family: 'Helvetica'; font-weight: bold; font-size: 1.8rem; `;
要使用函数组件并对 props 进行类型检查,你需要定义组件及其类型。这对 styled-components 来说并不特殊,这只是 React 的工作方式。
interface BoxProps { theme?: ThemeInterface; borders?: boolean; className?: string; } const Box: React.FunctionComponent<BoxProps> = (props) => <div className={props.className}>{props.children}</div>; const StyledBox = styled(Box)` padding: ${(props) => props.theme.lateralPadding}; `;
.extend
在 styled-components v4 中,.extend
API 被移除,请使用 styled(StyledComponent)
代替。更多信息,请查看:https://github.com/styled-components/styled-components/issues/1546
这是一个创建新的 StyledComponent
并扩展其规则的方法。
参数 | 描述 |
---|---|
| 一个标记模板字面量,包含您的 CSS 和插值。 |
import styled from 'styled-components' const Component = styled.div` color: red; ` const Component2 = Component.extend` background: white; color: blue; `
返回一个新的 StyledComponent
,其新规则与调用此方法的组件的规则合并。
injectGlobal
在 styled-components v4 中,injectGlobal
API 被移除,并用 createGlobalStyle
代替。
一个用于编写全局 CSS 的辅助方法。它不返回组件,而是直接将样式添加到样式表中。
参数 | 描述 |
---|---|
| 一个带标签的模板字面量,其中包含你的全局样式。 |
import { injectGlobal } from 'styled-components' injectGlobal` @font-face { font-family: "Operator Mono"; src: url("../fonts/Operator-Mono.ttf"); } body { margin: 0; } `
我们不鼓励使用它。如果你必须使用,请尝试在应用程序中最多使用一次,并且将其包含在一个文件中。这是一个逃生舱口。只在极少数情况下使用它,例如 @font-face
定义或主体样式。
"innerRef"
prop在 styled-components v4 中,"innerRef"
prop 被移除,取而代之的是 React 16 forwardRef
API。只需使用普通的 ref
prop 即可。
将 ref
prop 传递给样式化组件会给你一个 StyledComponent
包装器的实例,而不是底层的 DOM 节点。这是由于 refs 的工作方式。无法直接在我们的包装器上调用 DOM 方法,例如 focus
。
要获取对实际的、被包装的 DOM 节点的引用,请将回调传递给 innerRef
prop。
我们不支持字符串 refs(例如 innerRef="node"
),因为它们在 React 中已经过时了。
此示例使用 innerRef
保存对样式化输入的引用,并在用户悬停其上时将其聚焦。
const Input = styled.input` padding: 0.5em; margin: 0.5em; color: #BF4F74; background: papayawhip; border: none; border-radius: 3px; ` class Form extends React.Component { render() { return ( <Input placeholder="Hover here..." innerRef={x => { this.input = x }} onMouseEnter={() => this.input.focus()} /> ) } }
.withComponent
在 styled-components v4 中,withComponent
API 被 "as"
prop 代替,并在 v6 中完全移除。
这是一个创建新的 StyledComponent
的方法,其中应用了不同的标签或组件,但所有规则都与调用它的组件相同。
参数 | 描述 |
---|---|
| 一个有效的 React 组件或一个像 'div' 这样的标签名。 |
返回一个新的 StyledComponent
,在使用时会应用新的标签/组件。