问题
最近在开发需求中,发现调试组件的时候样式是正常的,但在顶层组件引用多个组件时会出现奇怪的ui展现。定位问题发现,不同组件或者父子组件如果类名有相同(常见如container,header, wrapper等),在引用时可能会出现意想不到的效果,但单个调试可以正常实现功能和界面。做了如下demo: demoA、demoB组件是同一层级,在顶层组件中使用。
会出现如下效果:可以看到组件A也引用到了组件B的样式。这是因为两个组件的css 样式没有限定作用域,导致在产物中被其他组件引用到了。
解决思路
在react中解决css污染问题有以下几种方案
-
在当前模块设置一个nameSpace, 以区分其他模块。嵌套组件仍会存在问题。
.componentA .title{
...
}
.componentB .title{
...
}
```
.componentA .title{
...
}
.componentB .title{
...
}
-
Css in js。如reactCSS写法如下。 都转化成了 JS 的写法,平时习惯了css模块化会有点不适应
class Component extends React.Component {
render() {
const styles = reactCSS({
'default': {
title: {
fontSize: '2.8rem',
color: this.props.color,
}
})
return (
<div style={ styles.card }>
</div>
)
}
}
-
模块化css文件。限定作用域。
a. 将.css文件后缀名改为.module.css
b. 引入css 样式对象
import styles from './index.module.css'
c. 使用样式
const DemoA: React.FC = () =>
<div className={styles.title}>DemoA颜色是红的</div>
原理:css module会将原始类名编译成一个哈希字符串,所以在产物中类名不会冲突。
Css module实际开发注意点
Css module区分全局:global和局部作用域:local,平时开发默认为局部作用域。在css文件中以下两种写法等效.
.title {
...
}
等价于
:local (.title) {
}
使用:global全局作用域类名不会被哈希编码,保留原类名。在引用第三方组件的时候可以使用该方法覆盖原有样式。也可以利用该方法引用到父组件的类名限定作用域。