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的情况,具有局限性。