不管是用 jquery 还是 react 开发,都会遇到的一系列 CSS 的问题:
通过 JS 来管理 CSS 就很好解决上述列举的问题。CSS 模块化的解决方案有很多,但主要有两类。
一类是彻底抛弃 CSS,使用 JS 或 JSON 来写样式。Radium, jsxstyle ,react-style 属于这一类。优点是能给 CSS 提供 JS 同样强大的模块化能力;缺点是不能利用成熟的 CSS 预处理器(或后处理器) Sass/Less/PostCSS, :hover 和 :active 伪类处理起来复杂。
另一类是依旧使用 CSS,但使用 JS 来管理样式依赖,代表是 CSS Modules。CSS Modules 能最大化地结合现有 CSS 生态和 JS 模块化能力。发布时依旧编译出单独的 JS 和 CSS。它并不依赖于 React,只要你使用 webpack,可以在 vue/Angular/jQuery 中使用。
- // webpack.config.js
- css?modules&localIdentName=[name]__[local]-[hash:base64:5]
加上 modules 即为启用, localIdentName 是设置生成样式的命名规则,[name] 表示标签名,[local] 表示类名,[hash:base64:5] 是按照给定算法生成的序列码。
- /* components/test.css */
- .active {
- color: red;
- }.disabled {
- color: gray;
- }
- /* components/test.js */
- import styles from './test.css';
- console.log(styles);
- elem.outerhtml = ` < h1 class = $ {
- styles.active
- } > CSS Modules < /h1>`/
生成的 HTML 是
- <h1 class="h1--active-abc53">
- Processing...
- </h1>
它将根据 styleName 的值在关联的 style 对象中查找对应的 CSS Modules,并为 ReactElement className 属性值添加相匹配的独一无二的 CSS 类名。
上例中 styles 的 consolelog 打印的结果是:
- Object {
- active: 'h1--active-abc53',
- disabled: 'h1--disabled-def84',
- }
CSS Modules 对 CSS 中的 class 名都做了处理,使用对象来保存原 class 和定制处理后的 class 的对应关系。经过这样类名定制处理后,class 名基本就是唯一的,大大降低了项目中样式覆盖的几率。同时可以生成更短的 class 名,减少代码量。
: 做
- :local
规则处理
- localIdentName
: 样式编译后不变
- :global
如果书写时不加,默认处理为
。
- :local
- .normal {
- color: green;
- }
- :local(.normal) {
- color: green;
- }
- /* 上面两个等价,默认给每个 class 名外加加了一个 `:local` */
- /* 全局样式 */
- :global {
- .link {
- color: green;
- }
- .box {
- color: yellow;
- }
- }
开启 CSS Modules 时定义的规则
会控制对 class 名的处理, [hash:base64:5] 定义的 hash 计算能保证类名的唯一性。
- localIdentName=[name]__[local]-[hash:base64:5]
很多时候我们都需要样式复用,在 CSS Modules 中,一个选择器可以继承另一个选择器的规则,这称为
组合。
- composes
- /* components/test.css */
- .bg {
- background - color: blue;
- }.title {
- composes: bg;
- color: white;
- }
- /* components/test.js */
- import styles from './test.css';
- elem.outerHTML = ` < h1 class = $ {
- styles.title
- } > CSS Modules < /h1>`/
生成的 HTML 为
- <h1 class="h1--bg-fec53 h1--title-Ijf8">
- Processing...
- </h1>
:export 关键字可以把 CSS 中的 变量输出到 JS 中:
- /* index.scss */
- $primary-color: #f40;
- :export {
- primaryColor: $primary-color;
- }
- /* app.js */
- import style from 'index.scss';
- // 会输出 #F40
- console.log(style.primaryColor);
- module: {
- loaders: [{
- test: /\.jsx?$/,
- loader: 'babel'
- },
- {
- test: /\.scss$/,
- exclude: path.resolve(__dirname, 'src/styles'),
- loader: 'style!css?modules&localIdentName=[name]__[local]!sass?sourceMap=true'
- },
- {
- test: /\.scss$/,
- include: path.resolve(__dirname, 'src/styles'),
- loader: 'style!css!sass?sourceMap=true'
- }]
- }
来源: