material UI是一個流行的與React配套的前端UI框架,對於開發者而言,熟悉它的樣式修改方案是必要的。但目前相關資料並不直觀,並且沒有總結到一起。如果對相關特性不太清楚,開發者很可能會在樣式上苦惱不已,本文主要根據筆者的開發經驗總結幾種常見的修改子組件樣式方案,有了這些方案,幾乎所有的情況都能應對了。
本文針對的是在父組件中修改子組件的樣式的情況,這是因為在當前組件中修改當前組件的樣式並沒有什么難度,而實際開發中復雜一點的情況幾乎都發生在父組件中修改子組件樣式的情況。
本文以withStyle
為例,makeStyle類似。
一、子組件根元素:withStyles+className
如果要在父組件中修改子組件的根元素,那么這相當於是在當前組件中修改當前組件的樣式,因為子組件根元素屬於父組件中直接可見的一個標簽。
直接給子組件應用className:
//父組件Parent.jsx中
<div>
<Child className={classes.child}></Child>
</div>
傳遞給withStyles的樣式對象:
const styles = {
child: {
color: 'red'
}
}
將樣式對象和父組件傳遞給withStyles,最后導出高階組件:
import { withStyles } from '@material-ui/core';
function Parent({classes}){
}
export default withStyles(styles)(Parent);
二、子組件的子孫元素:withStyles+className+&
如果要在父組件中修改子組件的子孫元素的樣式,那么會稍微復雜一些。事實上,只需要在樣式中嵌套即可。
給子組件的根元素設置好className:
//父組件Parent.jsx中
<div>
<Child className={classes.child}></Child>
</div>
在樣式對象中嵌套樣式來設置子組件的子孫元素:
const styles = {
child: {
color: 'red',
"& .title":{
color: 'blue'
},
"&$center":{
color: 'gray'
}
},
center:{
textAlign: 'center'
}
}
以上案例中,&
是占位符,代表當前選擇器;$
是變量標識,實質上是一個選擇器,$center代表styles中的center編譯后的類名。
現在,導出高階組件:
import { withStyles } from '@material-ui/core';
function Parent({classes}){
}
export default withStyles(styles)(Parent);
三、子組件的子孫元素:withStyles + classes
對於提供了樣式Api的子組件,也可以使用classes來直接設置,而不用像方案二那樣嵌套。
直接給子組件的classes屬性傳入對象,注意這里是classes屬性,而不是className屬性:
//父組件Parent.jsx中
<div>
<Child classes={{root:classes.child, text:classes.text}}>
</Child>
</div>
這樣,樣式對象child屬性中的css(即下面的color: 'red'
)將作用於child組件的css api中的root選項,查閱material ui可知,若child組件是Button組件,那么將在.MuiButton-root
元素上生效;樣式對象text屬性中的css(即下面的fontSize: '14px'
)將作用於child組件的css api中的text選項,查閱material ui可知,若child組件是Button組件,那么將在.MuiButton-text
元素上生效。
樣式對象:
const styles = {
child: {
color: 'red'
},
text:{
fontSize: '14px'
}
}
導出高階組件:
import { withStyles } from '@material-ui/core';
function Parent({classes}){
}
export default withStyles(styles)(Parent);
四、方案對比
- 方案一,適用於根元素樣式的修改。
- 方案二,具有普適性,它能夠應對各種場景。&和$符號使得該方案非常全能。
- 方案三,僅適用於框架恰好為要修改的元素提供了css api的情況,具有局限性。