styled
這是預設匯出。這是一個低階工廠,我們用它來創建 styled.tagname
輔助方法。
參數 | 說明 |
---|---|
| 一個有效的 React 組件或像 |
返回一個函式,該函式接受一個標籤樣板字面值並將其轉換為 StyledComponent
。
您可以在入門章節中看到此方法的介紹。
TaggedTemplateLiteral
這就是您傳遞給 styled 呼叫的內容 - 一個標籤樣板字面值。這是一個 ES6 語言特性。您可以在標籤樣板字面值章節中了解更多資訊。
輸入 | 說明 |
---|---|
規則 | 任何 CSS 規則(字串) |
插值 | 這可以是字串或函式。字串會按原樣與規則組合。函式將接收 styled component 的 props 作為第一個也是唯一的參數。 |
在根據 props 調整樣式章節中閱讀更多關於如何根據 props 調整樣式的資訊。
傳遞給插值函式的屬性會附加一個特殊屬性 theme
,該屬性由更高級別的 ThemeProvider
組件注入。查看主題章節以了解更多關於此資訊。
✨ Magic
您也可以從插值返回物件或直接輸入物件,它們將被視為內聯樣式。但是強烈建議不要這樣做,因為 CSS 語法支援偽選擇器、媒體查詢、嵌套等,而物件語法不支援。
StyledComponent
一個 styled 的 React 組件。當您使用樣式呼叫 styled.tagname
或 styled(Component)
時,會返回此組件。
此組件可以接受任何 prop。如果它是有效的屬性,它會將其傳遞給 HTML 節點,否則它只將其傳遞給插值函式。(請參閱標籤樣板字面值)
您可以將任意類名傳遞給 styled component,而不會出現問題,它將被應用於 styled 呼叫定義的樣式旁邊。(例如 <MyStyledComp className="bootstrap__btn" />
)
這是一個可鏈式方法,它將一些 props 附加到 styled component。第一個也是唯一的參數是一個物件,它將被合併到組件其餘的 props 中。 attrs
物件接受以下值
值 | 說明 |
---|---|
Prop 值 | 這些可以是任何類型,除了函式。它們將保持靜態,並將被合併到現有的組件 props 中。 |
Prop 工廠 | 一個接收傳遞給組件的 props 並計算值的函式,然後該值將被合併到現有的組件 props 中。 |
返回另一個 StyledComponent
。
在附加額外 Props章節中了解更多關於此建構函式的資訊。
"as"
多型 prop如果您想保留已應用於組件的所有樣式,但只想切換最終渲染的內容(無論是不同的 HTML 標籤還是不同的自定義組件),您可以使用 "as"
prop 在執行時執行此操作。
這種情況在導航欄等用例中非常有用,其中某些項目應該是連結,而有些只是按鈕,但都以相同的方式設定樣式。
如果您選擇使用也接受 "as"
prop 的 styled()
高階組件來包裝另一個組件,請使用 "forwardedAs"
將所需的 prop 傳遞給被包裝的組件。
如果您想防止將要由 styled components 使用的 props 傳遞到底層 React 節點或渲染到 DOM 元素,您可以使用貨幣符號 ($
) 作為 prop 名稱的前綴,將其轉換為暫態 prop。
在此範例中,$draggable
不像 draggable
那樣渲染到 DOM。
Drag me!
這是一種比暫態 props 更具動態性和粒度性的過濾機制。當多個高階組件組合在一起並且碰巧具有相同的 prop 名稱時,它會很方便。shouldForwardProp
的工作方式與 Array.filter
的謂詞回呼非常相似。未通過測試的 prop 不會向下傳遞到底層組件,就像暫態 prop 一樣。
請記住,如本例所示,其他可鏈式方法應始終在 .withConfig
之後執行。
Drag Me!
或者,shouldForwardProp
可以接受第二個參數,該參數提供對預設驗證器函式的訪問權限。此函式可以用作後備,當然,它也可以像謂詞一樣工作,根據已知的 HTML 屬性進行過濾。
ThemeProvider
一個用於主題的輔助組件。透過 context API 將主題注入到組件樹中其下方的所有 styled components 中。查看主題章節。
Props | 說明 |
---|---|
theme | 一個物件(或返回物件的函式),它將作為 |
簡單用法
I'm mediumseagreen!
使用巢狀的 ThemeProvider
新增或替換外部主題
I'm mediumseagreen with a white background!I'm mediumseagreen with a black background!
css
屬性有時您不想僅僅為了套用一些樣式就建立額外的組件。 css
屬性是一種方便的方式,讓您可以在不確定組件邊界的情況下迭代組件。它適用於普通的 HTML 標籤和組件,並支援任何樣式化組件支援的所有功能,包括根據 props、主題和自定義組件進行調整。
要啟用對 css
屬性的支援,您必須使用 Babel 插件。
<div css={` background: papayawhip; color: ${props => props.theme.colors.text}; `} /> <Button css="padding: 0.5em 1em;" />
在底層,Babel 插件會將任何具有 css
屬性的元素轉換為樣式化組件。例如,上面的程式碼會變成
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 />
請注意,您甚至不需要新增 import 語句,Babel 插件會自動執行!(除非您正在使用 Babel 巨集,請參見下文)
此功能已在 v6.1 中移除,因為使用率低且對其他使用者造成不必要的負擔。 更多資訊
您可以使用 Babel 巨集 使其在 create-react-app
中運作。不幸的是,Babel 巨集僅在導入時運行,因此**無法自動新增 import 語句。**如果您手動將 import 語句新增到巨集中,則上述程式碼可以完美運作
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 語句一次
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
一個輔助組件,用於修改樣式的處理方式。對於涉及 styled-components 的給定子樹,您可以自定義各種行為,例如 CSS 運行時處理器 (stylis) 如何透過使用者級插件和選項覆蓋來處理樣式。
Props | 說明 |
---|---|
disableCSSOMInjection (v5+) | 切換到較慢的基於文字節點的 CSS 注入系統,用於將樣式新增到 DOM。適用於與尚未升級以使用 CSSOM API 中樣式的第三方工具整合。 |
disableVendorPrefixes (v5,在 v6 中移除) | 選擇讓給定的子樹不為渲染的組件新增舊版 CSS 屬性。 |
enableVendorPrefixes (v6+) | 選擇讓給定的子樹為渲染的組件新增舊版 CSS 屬性。 |
sheet | *前方有龍*。如有必要,請為進階 SSR 情境建立並提供您自己的 StyleSheet。 |
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 中有效的任何內容在樣式化組件中都有效!
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}; `;
如果您正在 根據屬性調整樣式,並且這些屬性不是基本標籤/組件屬性的一部分,您可以使用類型參數,例如這樣告訴 TypeScript 這些額外的自定義屬性是什麼(需要 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 不會傳遞自定義屬性(以避免 未知屬性警告)。
但是,它會將所有屬性傳遞給自定義 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 組件,您可以利用 transient 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
根據您的使用情況,您可以通過自行提取自定義屬性來達到類似的結果
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; `;
要使用函數組件並對屬性進行類型檢查,您需要定義組件及其類型。這不是 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
定義或 body 樣式。
"innerRef"
屬性在 styled-components v4 中移除了 "innerRef"
屬性,改用 React 16 forwardRef
API。只需使用普通的 ref
屬性即可。
將 ref
屬性傳遞給樣式化組件將為您提供 StyledComponent
包裝器的實例,但不會提供底層 DOM 節點。這是由於 refs 的工作方式所致。無法直接在我們的包裝器上調用 DOM 方法,例如 focus
。
要獲取對實際包裝的 DOM 節點的引用,請將回調傳遞給 innerRef
屬性。
我們不支持字串 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"
屬性 取代,並在 v6 中完全移除。
這是一個建立新的 StyledComponent
的方法,它應用不同的標籤或組件,但所有規則都與調用它的組件相同。
參數 | 說明 |
---|---|
| 一個有效的 React 組件或像 'div' 這樣的標籤名稱。 |
返回一個新的 StyledComponent
,在使用它時應用新的標籤/組件。