zoukankan      html  css  js  c++  java
  • 运用 CSS in JS 实现模块化

    一、什么是 CSS in JS


    上图来源:https://2019.stateofcss.com/technologies/

    CSS in JS 是2014年推出的一种设计模式,它的核心思想是把 CSS 直接写到各自组件中,而不是单独的样式文件里。


    CSS in js 的发展:

    • 最早就是内联样式

    • 依旧使用 CSS,但使用 JS 来管理样式依赖,代表是 CSS Modules。

      这种方式在React框架中引入的。

    • 使用 JavaScript 生成 CSS 然后插入到页面中的方式。例如 Styled Components。

      CSS Module 还是 JS 和 CSS 分离的写法,而 styled components 实际上是在 JS 上写 CSS了。

    CSS in js 一次又一次的违背了 CSS 与 JS 分离的原则。

    二、常见的 CSS in JS


    1、CSS Modules

    CSS Modules 能最大化地结合现有 CSS 生态和 JS 模块化能力,API 简洁到几乎零学习成本。

    (1)安装

    CSS Modules 提供各种插件,支持不同的构建工具。本文使用的是 Webpack 的css-loader插件。

    CSS Modules不局限于你使用哪个前端库,无论是 React、Vue 还是 Angular,只要你能使用构建工具进行编译打包就可以使用。

    本文以 react 为例。下同。

    (2)全局/局部作用域

    CSS 是全局的,没有局部作用域的功能。

    但 CSS Modules 默认有局部作用域的概念,实现的方法为:使用独一无二的 class 名

    这个独一无二的 class 名,是一个 hash 值,css-loader默认的生成算法是[hash:base64],但 webpack 配置里面可以自定义格式。

    CSS Modules 只会对 className 以及 id 进行转换,其他的比如属性选择器,标签选择器都不进行处理,推荐尽量使用 className。

    写法 - js:

    import style from './App.css';
    
    <h1 className={style.title_1}>
    <h2 className={style.title_2}>
    

    写法 - css

    # 局部作用域的两种写法
    .title_1 {}
    
    :local(.title_1) {}
    
    # 全局作用域的两种写法
    :global(.title_2) {}
    
    :global {
      .title_2 {}
      # 还能继续添加……
    }
    

    生成 - html:

    <h1 class="_3zyde4l1yATCOkgn-DBWEL">
    
    <h1 class="title_2">
    

    生成 - css:

    ._3zyde4l1yATCOkgn-DBWEL {}
    
    .title_2{}
    
    (3)拓展 - 实现局部作用域的几种做法

    1、嵌套(很深)选择器

    .widget .table .row .cell .content .header .title {}
    

    2、使用 BEM 的 class 命名规范

    用很长的有规则的命名,来尽量实现唯一标识

    className="widget__header--active"
    

    参考我之前的文章《运用 CSS methodologies 去实现模块化》有介绍 BEM。

    3、css modules 的做法

    直接用 hash 生成 class 名。即没有方法1的嵌套,也绝对不会出现方法2中小概率的命名冲突问题。

    (4)组合 composition

    composes关键字可以让一个选择器可以继承另一个选择器的规则

    很像 less 里的继承。

    用处:

    1、可以引入别的模块,是实现模块化的一个必要功能。

    2、还能引入别的模块的部分样式。

    写法 - css:

    .title-base {
      background-color: blue;
    }
    
    # 1、来源于本文件
    .title {
      composes: title-base;
      color: red;
    }
    
    # 2、或 来源于别的文件
    .title {
      composes: title-base from './another.css';
      color: green;
    }
    

    生成 - html:

    <h1 class="_2DHwuiHWMnKTOYG45T0x34 _10B-buq6_BEOTOl9urIjf8">
    

    生成 - css:

    ._10B-buq6_BEOTOl9urIjf8 {
     background-color: blue;
    }
    
    ._2DHwuiHWMnKTOYG45T0x34 {
      color: red;
    }
    

    注意:这里是继承不是 mixin,所以这里没有混入所继承的选择器的属性,而是直接 addon 选择器名。减少了重复代码。

    (5)使用变量

    方法1:PostCSS 和 postcss-modules-values


    方法2:搭配 less / sass

    :export 关键字可以把 CSS 中的 变量输出到 JS 中。

    /* config.scss */
    $primary-color: #f40;
    
    :export {
      primaryColor: $primary-color;
    }
    
    /* app.js */
    
    import style from 'config.scss';
    // 会输出 #F40
    console.log(style.primaryColor);
    
    (6)结合

    1、跟 CSS 预处理器结合

    2、跟 BEM 等 CSS methodologies 结合

    可参考我之前的一篇文章:CSS methodologies 去实现模块化

    (7)实例

    react - jsx :

    import classNames from 'classnames';
    
    …………
    
          <div className={styles.header}>
            <ul className={styles.menu}>
              <li>1</li>
              <li>2</li>
              <li>3</li>
            </ul>
            <div className={styles.account}>
              <button
                type="button"
                className={classNames(styles.btnLogin, {
                  [styles.active]: !!this.state.active,
                })}
              >
                login
              </button>
              <button type="button" className={styles.btnRegister}>
                register
              </button>
            </div>
          </div>
    

    react - less :

    .header {
      color: blue;
      .menu {
        color: red;
        li {
          color: green;
        }
      }
      .account {
        color: orange;
        .btnLogin {
          font-size: 15px;
        }
        .btnRegister {
          font-size: 20px;
        }
        .btnLogin.active,
        .btnRegister.active {
          font-weight: bold;
        }
      }
    }
    

    注意点:

    1、因为使用了 css module 所以不用担心类名重复。可以舍弃掉 BEM 那种很长的类名,在保证基本语意化的前提下采取尽量简单的类名

    2、建议类名为驼峰,因为 js 里的 dot 取值形式对驼峰友好,而对styles.btn-login 会报错。

    3、可在 less 中采取 Combined Class Names (如 .btnRegister.active)或 Nested Class Names

    4、可以在 react 中用 classname 库提高书写效率(很适合搭配 state / props )。

    # classname 用法
    classNames('foo', 'bar'); // => 'foo bar'
    classNames('foo', { bar: true }); // => 'foo bar'
    classNames({ foo: true }, { bar: true }); // => 'foo bar'
    classNames({ foo: true, bar: true }); // => 'foo bar'
    

    5、写好多的styles.xxx很烦怎么办?可以用 babel-plugin-react-css-modules 自动加 styles 前缀。例子:

    import React from 'react';
    import CSSModules from 'react-css-modules';
    import styles from './table.css';
    
    class Table extends React.Component {
        render () {
            return <div styleName='table'>
                <div styleName='row'>
                    <div styleName='cell'>A0</div>
                    <div styleName='cell'>B0</div>
                </div>
            </div>;
        }
    }
    
    export default CSSModules(Table, styles);
    

    另外,还可以方便的覆盖本地变量的样式:

    import customStyles from './table-custom-styles.css';<Table styles={customStyles} />;
    

    6、更多实践请参考 ant design pro (https://pro.ant.design/docs/style-cn),它们用的正是 css modules + less。

    2、Styled Components

    (1)安装

    npm install styled-components

    (2)使用

    就拿一个 demo 举例:

    import styled from 'styled-components';
    
    const Wrapper = styled.section`
      margin: 0 auto;
       300px;
      text-align: center;
    `;
    const Button = styled.button`
       100px;
      color: white;
      background: skyblue;
    `;
    
    render(
      <Wrapper>
        <Button>Hello World</Button>
      </Wrapper>
    );
    

    注意:Styled Components 不支持 less 和 sass 语法。


    由于 Styled Components 有些激进,本人目前不打算深入了解。

    So,剩余部分待写。

    拓展


    1、CSS 预处理器 和 CSS 后处理器

    共同点:CSS 预处理器 和 CSS 后处理器 都属于 CSS 处理器。

    不同点:CSS 预处理器使用特殊的语法来标记需要转换的地方,而 CSS 后处理器可以解析转换标准的 CSS,并不需要任何特殊的语法。

    CSS 后处理器的代表就是 PostCSS ,PostCSS 是一个平台,其中最常用到的插件就是 autoprefixer

  • 相关阅读:
    springboot ssm propertis 如何搭建多数据源动态切换
    发送验证码
    二维码生成
    文件上传 下载
    git拉代码报错
    通过url 下载文件
    原生JS实现挡板小球游戏
    深入浅出解析AJAX
    深入解析CSS3圆周运动
    JS递归原理
  • 原文地址:https://www.cnblogs.com/xjnotxj/p/11584027.html
Copyright © 2011-2022 走看看