介紹
styled-component(以下稱SC) 是目前Css In Js 呼聲最高的一個套件。 透過 SC 可以快速產生一個具有可傳 Props 的物件同時又具有指定 html 類型的特性,除了在生成元件上速度非常快,也有一些擴充性可再利用的特性,非常的方便也支援 Reactnative ,原本寫 Sass Less Css 也不用太擔心,因為他有支援 ES6 Template Literals LITERALS 可以直接用原來的風格撰寫
開始使用
安裝SC npm install --save styled-components
馬上使用 在創建一個 SC 只需要 import styled from styled-components 之後就可以馬上使用,如下方 styled 後面加上 HTML 物件例如 h1,button,section,div..等等
這樣就會具有該 HTML 的特性又具有 SC 的一些 Props 功能 ,使用創建出來的Tag 還可以包其他TAG做出不同組合
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
render(
<Wrapper>
<Title>
Hello World, this is my first styled component!
</Title>
</Wrapper>
);
利用 SC 創建的物件可以直接指定參數 例如 下方的 Button的primary 傳入後可以在 Props 裡面使用 props.primary接收到
const Button = styled.button`
background: ${props => props.primary ? 'palevioletred' : 'white'};
color: ${props => props.primary ? 'white' : 'palevioletred'};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
render(
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);
SC 也可以在既有的元件上再掛上 Style ,以下範例有一個Link 用Styled使用HOC 包裝起來再使用ES6 Template Literals 語法包起來
const Link = ({ className, children }) => (
<a className={className}>
{children}
</a>
)
const StyledLink = styled(Link)`
color: palevioletred;
font-weight: bold;
`;
render(
<div>
<Link>Unstyled, boring Link</Link>
<br />
<StyledLink>Styled, exciting Link</StyledLink>
</div>
);
SC 也提供了動畫功能 import {keyframes} from 'styled-component'定一個 keyframes 的動畫在 SC 裡面給 animation 用 ES6 Template Literals 傳遞動畫的使用也非常方便
const rotate360 = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
const Rotate = styled.div`
display: inline-block;
animation: ${rotate360} 2s linear infinite;
padding: 2rem 1rem;
font-size: 1.2rem;
`;
render(
<Rotate>< ? ></Rotate>
);
在Next.js 設定 Theme 的部分也是在目錄 pages 底下創建一個 _document.js 檔案 因為 SSR 的部分有些程式碼是不能寫在 React dom 節點,這邊 getInitialProps SC 提供了一個 ServerStyleSheet
renderPage 就是在 APP 渲染之前加上一個 sheet.collectStyles 的 Wrap ,然後也在 Head 底下把 sheet.getStyleElement() 產出的 Style 打上去這樣就會有 SSR 的效果了
import Document, { Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'
export default class MyDocument extends Document {
static getInitialProps ({ renderPage }) {
const sheet = new ServerStyleSheet()
const page = renderPage(App => props => sheet.collectStyles(<App {...props} />))
const styleTags = sheet.getStyleElement()
return { ...page, styleTags }
}
render () {
return (
<html>
<Head>
<title>My page</title>
{this.props.styleTags}
</Head>
<body>
<Main />
<NextScript />
</body>
</html>
)
}
}
Theme 的部分 在 TopLevel 定義好 ThemeProvider 底下的 SC 都可以拿到 Theme 如下範例
const Button = styled.button`
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border-radius: 3px;
color: ${props => props.theme.main};
border: 2px solid ${props => props.theme.main};
`;
Button.defaultProps = {
theme: {
main: 'palevioletred'
}
}
const theme = {
main: 'mediumseagreen'
};
render(
<div>
<Button>Normal</Button>
<ThemeProvider theme={theme}>
<Button>Themed</Button>
</ThemeProvider>
</div>
);
使用 SSR 時候記得加上 .babelrc 檔案並安裝 Styled-component 的Plugin , 如果想要除錯方便也可以把 displayName 設定為 true 這樣在 className 的時候會多一個 component 的名稱,至於 preprocess 可以想成 Minify 性質是類似的,要使用的話則不能與 Minify 共用要選其一
{
"presets": [
"next/babel"
],
"plugins": [
["styled-components", { "ssr": true, "displayName": true, "preprocess": false } ]
]
}
總結
SC 在 React 的元件組裝上非常的容易上手,並且容易擴充,而在 Next.js 上使用要記得在 _document.js 補上 getInitialProps 產出 Tag 放在 Head 中, 並使用 SC 提供的 ServerStyleSheet 的工具,配合 Next.js 提供的 renderpage 重新 Wrap App dom
Next.js 範例 參考來源
https://github.com/zeit/next.js/tree/canary/examples/with-styled-components
以上範例都可以在官網查詢到
http://styled-components.com