一直在思考React組件如何拆分的問題,直到接觸到styled-components,讓我有一種如魚得水的感受,今天我就給你們分享一下這個庫如何讓咱們的前端組件開發的更優雅,如何保持更合適的組件拆分粒度從而更容易維護。css
styled-components是給React量身定製的一個庫,奉行React中all in js的設計理念,並將這個理念進一步發揮到極致,讓CSS也可以成爲一個個的JS模塊。html
使用起來也至關方便,首先安裝這個庫前端
npm install styled-components --save
複製代碼
而後在style.js中使用(注意這裏不是style.css,樣式文件所有是JS文件)html5
import styled from 'styled-components';
//styled.xxx表示建立xxx這個h5標籤,
//後面緊接的字符串裏面寫的是CSS代碼
export const HeaderWrapper = styled.div` z-index: 1; position: relative; height: 56px; border-bottom: 1px solid #f0f0f0; `;
複製代碼
以後再React中使用它:react
import React, {Component} from 'react';
import { HeaderWrapper } from './style.js';
class App extend Component{
render() {
return (
<HeaderWrapper></HeaderWrapper>
)
}
}
export default App;
複製代碼
Ok!這就是它的平常使用方式。若是有興趣能夠去github的相應倉庫打開更多使用姿式:)git
可能你還會有疑惑:這麼作有什麼好處呢?github
儘可能下降模塊之間的耦合度,利於項目的進一步維護。比起用原生的CSS,這是它首當其衝的優點。web
如:npm
export const SearchWrapper = styled.div`
position: relative;
float: left;
.zoom {
right: 5px;
&.focused {
background: #777;
color: #fff;
}
}
`;
複製代碼
能夠採用sass,less的嵌套語法,開發更加流暢。sass
不只僅是由於裏面的模板字符串能夠寫JS表達式,更重要的是可以拿到組件的上下文信息(state、props)
好比,在React組件中的JSX代碼中寫了這樣一段:
<RecommendItem imgUrl={'xxx'}/>
複製代碼
在相應的style.js中就可以接受相應的參數:
export const RecommendItem = styled.div` width: 280px; height: 50px; background: url(${(props) => props.imgUrl}); background-size: contain; `;
複製代碼
CSS可以拿到props中的內容,進行相應的渲染,是否是很是酷炫?
若是以上幾點還不能體現它的優點,那這一點就是對於前端開發者的毒藥。
如今不少人對標籤語義化的概念趨之若鶩,但其實大多數開發者都仍是div+class一把擼的模式。難道是由於語義化很差嗎?可以讓標籤更容易理解固然是件好事情,可是對於html5規範推出的標籤來講,一方面對於開發者來講略顯繁瑣,仍是div、span、h1之類更加簡潔和親切,另外一方面標準畢竟是標準,它並不能表明業務,所以並不具備足夠的表達力來描述紛繁的業務,甚至這種語義化有時候是無關緊要的。我以爲這兩點是開發者更喜歡div+class一把擼的根本緣由。
那好,照着這個思路,拿React組件開發而言,若是要想得到更好的表達力,儘量的語義化,那怎麼辦?可能你會暗笑:這還用說,拆組件啊!但組件真的是拆的越細越好嗎?
有人曾經說過:當你組件拆的愈來愈細的時候,你會發現每個組件就是一個標籤。可是這會形成一些更加嚴重的問題。假設咱們拆的都是UI組件,當咱們爲了語義化連一個button都要封裝成一個組件的時候,代碼會臃腫不堪,由於會出現數量過於龐大的組件,很是不利於維護。
那,有沒有一個折中的方案呢?既能提升標籤語義化,又能控制JS文件的數量。 沒錯,這個方案就是styled-components。
以首頁的導航爲例, 取出邏輯後JSX是這樣:
<HeaderWrapper>
<Logo/>
<Nav>
<NavItem className='left active'>首頁</NavItem>
<NavItem className='left'>下載App</NavItem>
<NavItem className='right'>
<i className="iconfont"></i>
</NavItem>
<SearchWrapper>
<NavSearch></NavSearch>
<i className='iconfont'></i>
</SearchWrapper>
</Nav>
<Addition>
<Button className='writting'>
<i className="iconfont"></i>
來參加
</Button>
<Button className='reg'>註冊</Button>
</Addition>
</HeaderWrapper>
複製代碼
//style.js
import styled from 'styled-components';
export const HeaderWrapper = styled.div` z-index: 1; position: relative; height: 56px; border-bottom: 1px solid #f0f0f0; `;
export const Logo = styled.div` position: absolute; top: 0; left: 0; display: block; width: 100px; height: 56px; background: url(${logoPic}); background-size: contain; `;
export const Nav = styled.div` width: 960px; height: 100%; padding-right: 70px; box-sizing: border-box; margin: 0 auto; `;
//......
複製代碼
拆分後的標籤基本是在style.js裏面導出的變量名,徹底自定義,這個時候CSS都成爲了一個個JS模塊,每個模塊至關於一個標籤(如:styled.div已經幫咱們建立好了標籤),在模塊下面徹底能夠再寫h5標籤。這樣的開發方式實際上是很是靈活的。
坑: 之前的injectGlobal已經被棄用,所以對於全局的樣式文件須要使用createGlobalStyle來進行引入。
//iconfont.js
//全局樣式同理
import {createGlobalStyle} from 'styled-components'
export const IconStyle = createGlobalStyle` @font-face { font-family: "iconfont"; src: url('./iconfont.eot?t=1561883078042'); /* IE9 */ src: url('./iconfont.eot?t=1561883078042#iefix') format('embedded-opentype'), /* IE6-IE8 //... } .iconfont { font-family: "iconfont" !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } `
複製代碼
而後在全局的根組件App.js裏面:
import { IconStyle } from './statics/iconfont/iconfont'
import { GlobalStyle } from './style'
//import ...
function App() {
return (
<Provider store={store}> <div> {/* 經過標籤形式引入這些樣式 */} <GlobalStyle></GlobalStyle> <IconStyle></IconStyle> <Header /> <BrowserRouter> <div> <Route path='/' exact component={Home}></Route> <Route path='/detail' exact component={Detail}></Route> </div> </BrowserRouter> </div> </Provider>
);
}
export default App;
複製代碼
對於styled-components缺點而言,我認爲目前惟一的不足在於模板字符串裏面沒有CSS語法,寫起來沒有自動提示,對於用慣IDE提示的人來講仍是有美中不足的。不過也並非什麼太大的問題,若是有相應的插件或工具歡迎在評論區分享。
對於styled-components以及組件化一點小小的思考,記錄一下,但願能對各位有啓發。