五分鐘 Styled-components 高級實用技巧

寫在前面的廢話

回到2013年,React憑空出世。可是在那時,咱們會想,oh shit! 咱們好不容易分離了HTML/CSS/JS, 爲何出現了JSX,咱們又須要把HTML和JS耦合在一塊兒?React 創造了 HTML in JS. 在React中,咱們知道,一切即組件。那既然HTML能在js裏寫,爲何咱們不把CSS也一塊兒寫呢?這樣不才是一個真正的組件嗎?javascript

Styled-components就是爲React而生的,它是CSS in JS的下一代解決方案。以往咱們想要作到css scope都須要在webpack中各類配置,或者使用js的解決方案。而styled-components你只須要import styled from 'styled-components';便可。css

甚至React完美的結合,不只是從TagName上,還有Props上。使咱們的代碼有更好的語義化,可維護性更強,效率更高。固然咱們無需考慮它的學習成本,只要你用過CSS或者SASS均可以馬上上手,由於它自己就是一種超集的存在。html

接下來,我會逐步的介紹一些這段時間以來,我很是喜歡的獨有的特性。java

開胃菜

const Button = styled.button` background: #abcdef; border-radius: 3px; border: none; color: white; `;
console.log(Button); //styled component
console.log(new Button()); // react component 

export default CustomButton extends React.component {
    render() {
        return <Button {...props} /> } } 複製代碼

styled-components 用了tagged template語法,直接爲咱們編寫樣式建立組件。react

繼承

styled-components繼承樣式有兩種寫法以下webpack

const Button = styled.button` background: #abcdef; border-radius: 3px; border: none; color: white; `;

const OtherButton1 = styled(button)``;
const OtherButton2 = button.extend``; // 老的寫法,不推薦,將來會被廢棄
複製代碼

寫法一的繼承,僅僅只會建立不同的css rule,而第二種寫法會複製一遍base component的css rule,而後在添加不同的進行css 權重覆蓋。不推薦git

固然,還有一種有趣的「繼承」 withComponent,咱們能夠利用withComponent改變渲染的標籤es6

const Li = styled.li` color:#abcdef; `;
const A = Li.withComponent('a'); // 將會渲染a標籤
複製代碼

編譯後他們會使用不一樣的className,這對咱們想用同個樣式,可是不一樣標籤很是有用。github

樣式覆蓋

這裏所說的樣式覆蓋,主要是一些交互上的行爲(hover, active)覆蓋。其實組件繼承也算是覆蓋的一種。web

以往咱們的覆蓋寫法以下:

const ListItem = styled.li` padding: 0; height: 48px; &.left-item-focus { .left-link { background: ${props => props.color}; } } &:hover { .left-icon { color: #9e9e9e; // 500 } } `;
複製代碼

而在styled中,咱們可使用styled-components 組件方式對咱們的DOM進行引用,從而覆蓋樣式,以下

const Icon = styled.span` color: red; `;

const ListItem = styled.li` &:hover ${Icon} { color: green; } `;
複製代碼

這依舊是咱們過去的思路來覆蓋樣式,只是咱們把選擇器直接使用styled組件引用罷了。擁有這樣的接口,就更加讓咱們無需去思考須要給組件取什麼className或者id,從而達到覆蓋樣式的作法。然而還有我最喜歡的另一種寫法。

TIPS:組件的引用必須是styled-components包裝後的組件,直接是react的會報錯

const ListItem = styled.li``;

const Icon = styled.span` color: red; ${ListItem}:hover & { // & 表明icon組件 color: green; } `;
複製代碼

這段代碼實現的是同樣的功能,只是咱們思路轉換了一下。能夠發現這樣的代碼更加沒有侵入性。更加符合開放封閉原則,當咱們不須要這個Icon組件時,直接把這個Icon刪除便可,咱們不用去父組件裏尋找與該組件有關的樣式,不容易形成樣式污染。忽然以爲眼前一亮,有木有!

固然這種「子組件引用父級」的功能,還有更加普遍的引用。你能夠選擇該DOM任何parent,再對本身進行樣式的覆蓋。以下:

const Icon = styled.span` color: red; html.ie-8 & { // fuck ie8 color: blue; } body.xxx & { color: green; } `;
複製代碼

當任何父級帶有class都會覆蓋Icon的樣式。這種「子組件引用父級」的功能也是我最喜歡的功能沒有之一。

在上面能夠看見咱們大量使用了&做爲選擇器,而&還有另外的技巧。

const Example = styled.li` color: red; & { color:blue; } && { color: green; } `;
複製代碼

你們能夠猜猜,這最終會渲染成什麼?

<li class='sc-gzVnrw fmpfVE'></li>
複製代碼

最終會編譯成以下class,可是咱們的一個&就表明一個class權重也就是說咱們最後會渲染原諒色,緣由是li被做用於了.fmpfVE.fmpfVE樣式表。這個功能很是有用,好比在你使用第三方組件想要覆蓋它的樣式的時候,咱們就能夠加多個&來提升樣式權重,從而覆蓋第三方組件的樣式

Theme

關於Theme只想說一點,那就是結合第三方組件應該如何傳入Theme呢?咱們有一個簡單的技巧。好比使用了Material-UI,若是咱們須要基於它拓展咱們本身的組件,而且須要樣式。

const ThemeProvider: React.SFC<ThemeProviderProps> = ({ themeName, children }) => {
  const theme = themes[themeName];
  return (
    <StyledThemeProvider theme={theme}> <MuiThemeProvider theme={theme}> {React.Children.only(children)} </MuiThemeProvider> </StyledThemeProvider>
  );
};
複製代碼

以後只須要把咱們須要調用的組件使用styled-components提供的withTheme包裝一下咱們的組件來獲取咱們的theme。

這樣既能夠在咱們的styled-components裏取到theme,material裏也能夠了。

以上就是咱們全部的技巧了, 看了這麼多有意思的黑科技,難道你還不愛上styled-components嗎?

我的網站 www.meckodo

Github: github.com/MeCKodo

相關文章
相關標籤/搜索