React css污染解决方案

665 阅读2分钟

问题

最近在开发需求中,发现调试组件的时候样式是正常的,但在顶层组件引用多个组件时会出现奇怪的ui展现。定位问题发现,不同组件或者父子组件如果类名有相同(常见如container,header, wrapper等),在引用时可能会出现意想不到的效果,但单个调试可以正常实现功能和界面。做了如下demo: demoA、demoB组件是同一层级,在顶层组件中使用。

image.png 会出现如下效果:可以看到组件A也引用到了组件B的样式。这是因为两个组件的css 样式没有限定作用域,导致在产物中被其他组件引用到了。

image.png

解决思路

在react中解决css污染问题有以下几种方案

  1. 在当前模块设置一个nameSpace, 以区分其他模块。嵌套组件仍会存在问题。

.componentA .title{
...
}

.componentB .title{
...
}
```
.componentA .title{
...
}

.componentB .title{
...
}
  1. 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>     
  )   
} 
}

  1. 模块化css文件。限定作用域。

a. 将.css文件后缀名改为.module.css

b. 引入css 样式对象

import styles from './index.module.css'

c. 使用样式

const DemoA: React.FC = () => 
  <div className={styles.title}>DemoA颜色是红的</div>

image.png 原理:css module会将原始类名编译成一个哈希字符串,所以在产物中类名不会冲突。

Css module实际开发注意点

Css module区分全局:global和局部作用域:local,平时开发默认为局部作用域。在css文件中以下两种写法等效.

.title {
...
}
等价于
:local (.title) {
}

使用:global全局作用域类名不会被哈希编码,保留原类名。在引用第三方组件的时候可以使用该方法覆盖原有样式。也可以利用该方法引用到父组件的类名限定作用域。