react中經過jsx的語法方式,將html標籤和js語法聯繫在一塊兒,而css的編寫方式,沒有明確的指定編寫方式,目前就有不少不一樣方法,每一個方式各有其優缺點,咱們一塊兒來看看經常使用的定義方式有哪些。css
最基礎也是最簡單的方式就是如html當中編寫樣式同樣,直接內聯使用,區別在於jsx中內聯使用樣式須要用小駝峯命名,不可以使用短橫線 -,jsx中編寫js的表達式須要使用 {},而定義的樣式是以對象的形式存在,也是經過{},因此看起來style標籤裏面使用了兩個大括號{}html
return(<div style={{color: 'blue'}}> hello react </div>)
這樣的方式優勢是代碼不會衝突,定義的代碼都做用於當前元素,並且若是須要動態的獲取state的值來設置樣式也能夠作到。缺點也很明顯,當若是樣式很是多的時候,即便把樣式總體提煉出來,做爲一個變量賦值給style,但仍然仍是和業務邏輯混雜在一塊兒,而且沒法編寫僞類等一些語法。react
第二種方式可以將css代碼與業務邏輯代碼分離開來,在jsx的標籤中定義className屬性,自定義css的樣式文件,再經過import引入css/scss/less等樣式文件,就是使用的css的原生編寫方式,定義僞類以及其它的高級選擇器編寫方式均可以支持。es6
return(<div className="title"> hello react </div>) // 定義在單獨的樣式文件 .title { color: 'blue' }
這樣可讓代碼比較清晰明瞭,css樣式和jsx文件分離開。數組
當須要使用多個className,或者經過狀態來變動className時,能夠經過+來進行字符串拼接,或者使用數組,再經過toString()轉成字符串less
const isActive = true <h2 className="active foo bar">我是標題1</h2> // active foo bar <h2 className={"foo", (isActive ? "active" : "") }>我是標題2</h2> // active <h2 className={"foo" + (isActive ? " active" : "") }>我是標題3</h2> // foo, active <h2 className={["foo",(isActive ? "active" : "")]}>我是標題4</h2> // foo, active <h2 className={["foo",(isActive ? "active" : "")].join(" ")}> 我是標題5</h2> // foo avtive
爲了簡便使用,能夠直接使用 classnames 這個庫來動態的使用類名,classnames默認暴露了一個函數,傳入參數的參數能夠爲字符串、對象和數組,傳入null/undefined/boolean值也不會顯示在頁面上ide
import classNames from 'classnames' const isShow = false const list = ['foo', 'bar'] <h2 className={classNames({"active": isActive}, "foo")}> 我是標題6</h2> // active foo <h2 className={classNames({"active": isActive, "bar": isShow })}> 我是標題7</h2> // active <h2 className={classNames({"active": isActive}, list)}> 我是標題8</h2> // active foo bar <h2 className={classNames(null, undefined, 0, 10, '0', true, false)}> 我是標題8</h2> // 10 0
但react開發的頁面都叫作單頁面應用,整個項目只有一個頁面,樣式在a組件引用,b組件即便沒有引用,定義了同名的類名,也會有樣式,這樣致使若是c組件和d組件都定義了className屬性,分別引入了css樣式定義字體顏色,但最終二者呈現出的字體顏色爲後引入的css文件裏的字體顏色,即同名的樣式會被覆蓋掉。模塊化
爲了解決這一問題,咱們就須要在跟標籤處再定義一個className,來包裹當前組件的全部標籤,這樣css樣式的層級就比較多,而且還可能由於選擇器優先級的問題(在外層定義了id選擇器),而產生樣式衝突,同時它不支持獲取state屬性動態設置樣式。函數
return(<div className="homeComponent"> <div className="title">hello react</div> </div>)
此時就產生了第三種編寫方式,css的模塊化,這樣的方式能夠區分各個組件的樣式,不會相互覆蓋,並且還能定義僞類,react腳手架當中內置了css modules的配置,咱們能夠直接將css的文件定義爲 xxx.module.css,在xxx.module.css文件中,仍是按照之前的css編寫方式編寫,不一樣點在於jsx頁面中定義className,先引入該css文件,而後定義類名以對象的形式定義字體
import style from './index.module.css' return(<div className={style.title}> hello react </div>)
這樣定義的樣式是一個不會重複的字符
這樣一種定義樣式的方式可以比較有效的解決樣式重疊的問題,麻煩之處就是每次編寫樣式的時候須要經過對象的語法來定義,而且不支持動態的設置樣式。
那麼就有了第四種方式,css in js,這是一種代碼的理念,react中html和js沒有分離,那麼css也能夠不分離,以js的方式來編寫css,使css的編寫更加的靈活,既能夠像以前寫css同樣編寫,又能夠動態的獲取屬性。這種編寫方式須要依賴其它庫,這裏使用經常使用的 styled-components來演示。
使用 styled-components以前須要對es6模板字符串的一種語法有了解,咱們可使用模板字符串來對字符串和屬性進行拼接,在此以前的拼接可能都須要使用 +
const name = 'kiki' const age = '18' const user = `my name is ${name}, age is ${age}` console.log(user) // my name is kiki, age is 18
但模板字符串還有一種用法,就是它能夠像小括號同樣調用函數,而且參數以必定的規則傳遞給函數
let name = 'kiki', age = 18 function foo(...args){ console.log(args) } foo`hello` foo`my name is ${name}, age is ${age} `
基於模板字符串的這種使用方式,咱們來看看 styled-components 如何使用,先從styled-components的默認暴露中引入函數,建立一個div標籤,並在模板字符串中定義樣式,最後將建立的組件替換div標籤,經過js定義的組件均可以抽取到一個單獨的js文件當中,這裏爲了演示方便,就寫在了一塊兒。
import React, { PureComponent } from 'react' import styled from 'styled-components' const DivStyle = styled.div` background-color: gray; color: #fff; font-size: 20px; ` export default class Profile extends PureComponent{ render(){ return(<div> <DivStyle>我是Profile組件的內容</DivStyle> </div>) } }
這樣看起來編寫方式更爲複雜了,但其實它還有不少好用的方式,除了使用樣式,咱們可能還對有些標籤要作一些別的屬性設置,以及咱們須要經過當前頁面維護的state屬性來區分樣式的展現,在定義樣式的時候,value值以函數的形式從props中獲取屬性
import React, { PureComponent } from 'react' import styled from 'styled-components' const InputStyle = styled.input.attrs({ type: 'text', placeholder: '請輸入內容', })` color: ${props => props.color} ` export default class Deliver extends PureComponent{ constructor(props){ super(props) this.state = { color: 'purple' } } render(){ return(<p> <InputStyle type="password" color={this.state.color}/> </p>) } }
樣式當中,若是有重複的定義樣式方式,要麼須要定義多個className,要麼就得重複定義,styled-components提供了繼承的方式使樣式能夠複用,經過styled-components中默認暴露的導出函數,直接傳入已定義好樣式的組件
import React, { PureComponent } from 'react' import styled from 'styled-components' const DivStyle = styled.div` background-color: gray; color: #fff; font-size: 14px; ` const RecommondStyle = styled(DivStyle)` font-size: 20px; ` export default class Profile extends PureComponent{ render(){ return(<div> <DivStyle> hello styled-components </DivStyle> <RecommondStyle> style屬性的繼承 </RecommondStyle> </div> ) } }
另外,還能夠給最外層的組件定義一個主題,這樣它定義的樣式子元素均可以從props中獲取到
// 父組件 import { ThemeProvider } from 'styled-components' export default class Home extends PureComponent{ render(){ return(<ThemeProvider theme={{color: 'brown'}}> <About/> </ThemeProvider>) } } // 子組件 import React, { PureComponent } from 'react' import styled from 'styled-components' const DivStyle = styled.div` color: ${props => props.theme.color}; ` export default class About extends PureComponent{ render(){ return(<DivStyle> style設置主題 </DivStyle> ) } }
這樣一種css的編寫方式使得css的代碼更像js,很是的靈活,也更具備複用性。
以上四種樣式在react當中的定義方式是比較經常使用的,能夠根據狀況結合使用~