使用recompose,如何在Material-UI v1中合并两个样式对象导出组件?
解决Material-UI v1 + recompose合并组件样式与全局样式的问题
嗨,我之前也碰到过一模一样的场景,核心问题其实是withStyles本身不支持直接传入多个样式对象——要是你连续调用两次withStyles(一次传全局样式,一次传组件样式),后面的会直接覆盖前面生成的classes,所以得换个思路:先手动合并两个样式对象,再传给withStyles。
下面给你两种最常用的解决方案,根据你的样式类型选就行:
方案一:静态样式对象合并
如果你的全局样式和组件样式都是静态的(不依赖theme或props),直接用ES6对象扩展运算符...或者Object.assign合并就好,组件样式放后面可以覆盖全局样式的同名类:
import { withStyles } from '@material-ui/core/styles'; import { compose } from 'recompose'; // 导入全局通用样式 import globalStyles from '../styles/GlobalStyles'; // 组件内部样式 const localStyles = { root: { backgroundColor: '#f5f5f5', borderRadius: 4 }, button: { marginLeft: 8 } }; // 合并样式:全局样式在前,组件样式在后(同名类会被组件样式覆盖) const mergedStyles = { ...globalStyles, ...localStyles }; const MyComponent = ({ classes }) => ( <div className={classes.root}> <button className={classes.button}>点击我</button> </div> ); // 用recompose的compose包装withStyles export default compose( withStyles(mergedStyles) )(MyComponent);
方案二:依赖Theme的动态样式合并
如果你的全局样式是依赖Material-UI Theme的函数(比如全局样式里用了theme.spacing或主题色),那组件样式也可以写成函数,然后合并两个函数返回的对象:
import { withStyles } from '@material-ui/core/styles'; import { compose } from 'recompose'; // 全局样式是接收theme参数的函数 import globalStyles from '../styles/GlobalStyles'; // 组件本地样式同样写成接收theme的函数 const localStyles = (theme) => ({ root: { padding: theme.spacing(2), backgroundColor: theme.palette.grey[100] }, button: { color: theme.palette.primary.main } }); // 合并两个函数的返回结果 const mergedStyles = (theme) => ({ ...globalStyles(theme), ...localStyles(theme) }); const MyComponent = ({ classes }) => ( <div className={classes.root}> <button className={classes.button}>主题按钮</button> </div> ); export default compose( withStyles(mergedStyles) )(MyComponent);
关键注意点
- 优先级控制:合并时后面的对象会覆盖前面的同名属性,所以如果想让组件样式覆盖全局样式,就把组件样式放在
...后面;如果想全局样式优先级更高,就调换顺序。 - 不要多次调用withStyles:如果分开写
compose(withStyles(globalStyles), withStyles(localStyles)),第二次的withStyles会完全替换第一次生成的classes,导致全局样式失效,所以必须合并后再传入一次withStyles。
内容的提问来源于stack exchange,提问作者connect2Coder
相关产品推荐
相关产品推荐

