CSS module和React 中的应用

为什么需要CSS模块化 ?

由于CSS的规则是全局性的,添加任何一个样式,在全局都有效,优点是方便复用,缺点是会根据权重的计算造成样式冲突,非常难以管理。

CSS 模块化的方案

有了钉子,自然就会有锤子。随着前端的发展出现了各种CSS模块解决方案,主要分两种:
一类是采用JS或者JSON 的方式写CSS,比如 jsxstyle,react-style,虽然可以采用JS成熟方案来管理css, 但是它无法使用postcss ,sass等css预处理器,并且衍生了大批的api, 使用的代价较大。
另一类还是采用css 来写样式, 不过是通过工具生成CSS作用域的方式实现模块化,比如CSS module。常用的BEM命名技巧或者团队中约定的方案来实现命名空间从而实现模块化,不过约定总会出现问题,于是就出现了通过工具,比如webpack的css-loader根据算法,实现css 模块化。

启用CSS

webpack 内置的 css-loader 自带了CSS modoule, 配置如下:

rules: [
      ...
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
              localIdentName: '[name]__[local]--[hash:base64:5]' // 生成样式的命名规则
            }
           //或者采用loader: 'css?modules&localIdentName=[name]__[local]-[hash:base64:5]'的写法
          }
        ]
       }
    ]

create-react-app 2.0以上的版本中内置启动了CSS module, 如果需要特殊配置,则需要eject操作, 在webpack.config.js 中:

 // Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
      {
          test: cssModuleRegex,
          use: getStyleLoaders({
          importLoaders: 1,
          sourceMap: isEnvProduction && shouldUseSourceMap,
          modules: true,
          getLocalIdent: getCSSModuleLocalIdent,
          }),
      },
      

CSS module 用法

基本用法
/* components/Button.css */
.normal { /* normal 相关的所有样式 */ }
.disabled { /* disabled 相关的所有样式 */ }

// components/Button.js
import styles from './Button.css';
buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

//生成的HTML
<button class="button--normal-abc53">Submit</button>

CSS module 默认采用局部样式,即给每个css 名添加上了“:local”, 对应的全局性的写法:

/* 定义全局样式 */
:global(.btn) {
  color: red;
}

/* 定义多个全局样式 */
:global {
  .link {
    color: green;
  }
  .box {
    color: yellow;
  }
}

compose 组合样式:
对于样式复用,CSS module提供了唯一的方式 "compose":

/* components/Button.css */
.base { /* 所有通用的样式 */ }

.normal {
  composes: base;
  /* normal 其它样式 */
}

.disabled {
  composes: base;
  /* disabled 其它样式 */
}

import styles from './Button.css';
buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

// 生成后的html
<button class="button--base-fec26 button--normal-abc53">Submit</button>

多CSS class 的写法:

.normal {
  composes: base;
  /* normal 其它样式 */
}

.disabled {
  composes: base;
  /* disabled 其它样式 */
}

import styles from './Button.css';
buttonElem.outerHTML = `<button className={ `${styles.normal}  ${style.disbale} `}>Submit</button>`

Sass 变量与JS共享

/* config.scss */
$primary-color: #f40;

// 内置语法,可以到处该变量
:export {
  primaryColor: $primary-color;
}

/* app.js */
import style from 'config.scss';

// 会输出 #F40
console.log(style.primaryColor);
使用技巧

Css module 作者建议:
1.不使用选择器,只使用 class 名来定义样式
2.不层叠多个 class,只使用一个 class 把所有样式定义好
3.不嵌套
4.使用 composes 组合来实现复用

Css module 在React中的实践

采用classnames来增强CSS module 在react 中的使用,类似Angular 中的样式指令:

var classNames = require('classnames');

class Button extends React.Component {
  // ...
  render () {
    var btnClass = classNames({
      btn: true,
      'btn-pressed': this.state.isPressed,
      'btn-over': !this.state.isPressed && this.state.isHovered
    });
    return <button className={btnClass}>{this.props.label}</button>;
  }
}
应用全局样式
...
// 引入全局样式 
import 'xxx/common.css';
// 引入局部样式
import styles from './xxx.module.css';
...
<div className={styles.wrapper}>
  <!-- 同时引入全局、局部样式,且如果className带中划线,用['className']代替 -->
  <button className={`btn ${styles['my-btn']}`}>save</button>
</div>
...

参考链接:https://zhuanlan.zhihu.com/p/20495964

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 28,199评论 1 45
  • 学习流程 参考文档:入门Webpack,看这篇就够了Webpack for React 一. 简单使用webpac...
    Jason_Zeng阅读 8,347评论 2 16
  • 目录第1章 webpack简介 11.1 webpack是什么? 11.2 官网地址 21.3 为什么使用 web...
    lemonzoey阅读 5,689评论 0 1
  • 朋友说, 父亲今日去世, 一切安好,勿挂心。 但我不想只在伤痛时才去抚慰。 所以你未收到我的讯息, 未收到我的不安...
    伊思xxx阅读 3,153评论 0 7
  • 不是爱情不肯放过你,不是回忆不肯放过你,不是宿命不肯放过你,而是你自己不肯放过你自己。 我们终于变成了我 你
    梦琪琪昂阅读 1,823评论 0 1

友情链接更多精彩内容