CSS module和React 中的应用

作者: Lingli_yu | 来源:发表于2019-07-03 13:33 被阅读0次

    为什么需要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

    相关文章

      网友评论

        本文标题:CSS module和React 中的应用

        本文链接:https://www.haomeiwen.com/subject/nsafhctx.html