這么久以來,各種各樣的框架試圖讓 web 組件化穴亏。到目前為止蜂挪,react 基本做到了這一點:用一個自定義標(biāo)簽的方式組織 html 在一起。
<Wrapper>
<Header />
<ProductList />
<Footer />
</Wrapper>
上面的這種寫法在傳統(tǒng)的 web 開發(fā)中真是不敢想象嗓化,然而在 react 中的確實現(xiàn)了棠涮。如果你使用 create-react-app
這樣的腳手架工具,你可以快速的搭建起來這樣的體系刺覆。然而严肪,即便是這樣子,web 組件化依然有一個點沒有解決:如何將樣式和組件綁定在一起。當(dāng)然驳糯,試圖解決這個問題的工具有很多篇梭,也有很多人不認(rèn)為這是一個問題。我在這里試圖解釋一些觀點酝枢,并闡述為什么我覺得用 styled-components
可以在一定程度上解決一系列問題恬偷。
寫 css 的最佳方式
目前,react 陣營對寫 css 這個問題有兩個陣營帘睦。一個陣營表示 css 應(yīng)當(dāng)和 js 寫在一起袍患,而另一個陣營則認(rèn)為 css 原本是可以和 js 分離的。我們在這里做一個簡單的例子竣付。
首先是 css in js 的例子:
const style = {
margin: "1em 2em",
color: "gray",
background-color: "white"
};
const StyledDiv = (props) => {
return <div style={style}>A test</div>
};
而 css 和 js 分離就很簡單了:
.styled-div {
margin: 1em 2em;
color: gray;
background-color: white;
}
import "./StyledDiv.css";
const StyledDiv = (props) => {
return <div className="styled-div">A test</div>
};
當(dāng)然诡延,這里展示的 css in js 只是一種非常原始的方式:用 object 直接將 style 注入到組件中古胆。這樣做的好處有兩個:
- css 不在是全局的了,style 的生命周期與生命范圍終于和 component 一致了赤兴,那么因為全局變量導(dǎo)致的可怕的為何災(zāi)難緩解了
- 在組件內(nèi)對樣式的操縱可以直接進(jìn)行,無需通過 className 處理桶良,當(dāng)然也避免了創(chuàng)建全局的 className 了
可以看到,這里基本上就是以解決 css 的全局性為出發(fā)點的陨帆。
而 css 和 js 的分離當(dāng)然也有其天然的優(yōu)勢:
- 可以用 css 的方式寫 css,css 選擇器隨便用
- 我還可以加各種 preprocessor 和 post processor疲牵,比如寫 scss 比如加 auto-prefix
對我來說,用 object 的方式去寫 css 體驗實在是太差了纲爸。而且作為 css
的 cascade
,如果不能用多級的選擇器去定位 css 而是在一層層的 html 元素中添加樣式簡直就是噩夢识啦。我不覺得這樣的可維護(hù)水平比全局 css 要高...所以我覺得如果能把兩者的優(yōu)勢結(jié)合在一起,就應(yīng)該是一個可以被更多人介紹的方式:
- 用 css 的語法寫 css
- 能創(chuàng)建局部 className
- 支持 preprocessor 和 postprocessor
那么在這里就不得不提另外一個有意思的東西:css-modules颓哮。它的主要思想是通過為 css 生成隨機的類名稱的方式來建立一種局部類命名的方式。
styled-components
基本上集成了這個工作冕茅,并在此基礎(chǔ)上基本實現(xiàn)了以上的三點要求蛹找。
const Summary = styled.div`
margin-top: 2em;
text-align: right;
.price {
color: #ff0036;
font-size: 1.2em;
}
&> * {
display: inline-block;
margin-left: 1em;
}
`;
-
Summary
的 css 是以 css 的方式編寫的,支持多層次的定義 -
styled-components
會把上面定義的 css 以一個特別的 className 的方式注入到元素上庸疾,實現(xiàn)了局部類定義 -
styled-components
支持了基本的類似于 scss 的嵌套語法(還支持 extend 語法,這里并沒有展示)彼硫,并且內(nèi)嵌了autoprefix
的模塊
我最近開始在一個項目上使用它炊豪,整體來說還是感覺不錯。
兼容現(xiàn)在已有的 react components 和 css 框架
styled-components
采用的 css-module 的模式有另外一個好處就是可以很好的與其他的主題庫進(jìn)行兼容词渤。因為大部分的 css 框架或者 css 主題都是以 className 的方式進(jìn)行樣式處理的,額外的 className 和主題的 className 并不會有太大的沖突缺虐。你可以認(rèn)為這是一個應(yīng)當(dāng)使用全局 css 的地方(所以我并不贊成用 styled-components 里面的 theming 接口去做這件事)。相對于以 object 的方式寫 style 的 material-ui 真是好太多了高氮,看看 material-ui 講述如何進(jìn)行樣式自定義就知道這并不是一個很成熟的想:
- css 內(nèi)嵌到組建里影響了組件自身結(jié)構(gòu)的表現(xiàn)
- inline style 意味著最高的優(yōu)先級,其無法和其他的主題庫配合
styled-components
的語法同樣支持對一個 React 組件進(jìn)行擴展:
const StyledDiv = styled(Row)`
position: relative;
height: 100%;
.image img {
width: 100%;
}
.content {
min-height: 30em;
overflow: auto;
}
.content h2 {
font-size: 1.8em;
color: black;
margin-bottom: 1em;
}
`;
這里我把 ant design 做為我默認(rèn)的樣式庫剪芍,在其基礎(chǔ)上我對其一些元素做了增強。兩者可以很好的在一起使用罪裹。
這里符一個 github 項目 里面包含了很多使用 styled-components
的例子。