在讲CSS Modules之前,先想想什么是CSS Module?
在我眼中CSS Module是对css进行模块化的管理,更加深入的解释就是用来管理css样式的导入与导出。灵活按需导入以便复用代码,导出的时候要合理的分割域的界限。
CSS Module面对的问题
模块化实际过程中遇到的问题有如下几点:
- 样式污染
- 命名混乱
- 无法共享变量,具体来说,在主题样式文件库中设置了默认样式,然后想要在js中去获取,在原先的css体系中很难做到,你要通过dom查询去获取对应的样式。
- 代码压缩不彻底,比如说,你用了sass、less之类的内容,他们会在被包裹的类名上再加上包裹他的类名,无法做到很好地压缩
进程后移,CSS Module的发展中,出现了sass、less等一系列解决css编程能力弱的问题和样式污染的问题,但是他们并没有很好地解决模块化其他的问题
在之前,还出现过一种方案叫 css in js,这种写法相当于完全抛弃了css,在js中通过hash映射来写css,这个写法的好处和坏处都很明显。
然后就是我们的CSS Modules, CSS Module的问题他都能解决的比较好
CSS Modules
CSS Modules的官方文档如下:github.com/css-modules…
简单的例子来描述写它的使用方式,
首先在webpack中进行对应的设置,之后进行对应的引用
/*webpack.js*/
css?modules&localIdentName=[name]__[local]-[hash:base64:5]
/*Button.css*/
.normal{}
.disabled{}
/*Button.js*/
import styles from './Button.css'
render(){
reutrn(
<button class=${styles.normal}></button>
)
}
最终生成的html如下
<button class="button-normal-abc5436"></button>
后面的abc3546是按照localIdentName自动生成的class名称,按照给定算法生成的序列码,这样处理之后,大大降低了项目中样式覆盖的几率 。同时生成更短的class名可以提高css的压缩效率
默认情况下,样式是局部内容,如果要切换成全局的样式可以用:global进行包裹
样式复用在CSS Modules中也是可以做到的,相对于less sass来说麻烦一点,需要用composes来组合样式,当然现在CSS Modules也是可以结合less的
.base{}
.normal{
composes:base
}
以上CSS Modules的命名规则是源于BEM的。BEM是一种css命名模板,具体内容如下:
B:block,对应模块名,如dialog
E:element 对应模块中的节点,如button
M:modifier 对应节点的状态,disabled
最终class名 dialog__button--disabled 在很多大型项目中都可以看到这样的命名写法
CSS Modules实现变量共享
config.css
css{
$primary-color:#ffffff;
}
app.js
import style from 'config.css'
console.log(style.primaryColor)
解决频繁书写styles的副作用
不过CSS Modules在实际开发中会带来书写的副作用,每一个class前面都需要加一个styles,这样增加了书写的负担,如果不想频繁的书写,可以使用react-css-modules库,通过高阶组件的形式避免重复输入css 核心代码如下:
import React,{Component} from 'react'
import styles from './config.css'
import CSSModules from 'react-css-modules'
class Dialog extends Component{
render(){
return(
<div styleName={root}></div>
)
}
}
export default CSSModules(Dialog,styles)
这样书写之后的好处有如下几个:
- 省去了styles的重复书写
- 如果想要写全局样式,直接用className书写就可以
- styleName关联一个undefined的CSS Modules时,我们可以得到一个警告
- 保证css的样式来源的单一明了