www.22138com「太阳集团游戏」太阳2007娱乐官方网址

欢迎更多朋友与我们www.22138com合作,太阳集团游戏是由安全软件管理软件整合而成的最新安全卫士,其实这是因为目前已经推出了太阳2007娱乐官方网址的新网址,带您体验至尊级享受!。

阅读本文需要 11m 24s

2019-11-23 22:19 来源:未知

CSS Modules 入门及 React 中实践

2017/03/25 · CSS · React

原文出处: AlloyTeam   

写在前面

读文先看此图,能先有个大体概念:

www.22138com 1

阅读本文需要 11m 24s。

CSS Modules介绍

CSS Modules是什么东西呢?首先,让我们从官方文档入手:
GitHub – css-modules/css-modules: Documentation about css-modules

A CSS Module is a CSS file in which all class names and animation names are scoped locally by default. CSS模块就是所有的类名都只有局部作用域的CSS文件。

所以CSS Modules既不是官方标准,也不是浏览器的特性,而是在构建步骤(例如使用Webpack或Browserify)中对CSS类名选择器限定作用域的一种方式(通过hash实现类似于命名空间的方法)。

It doesn’t really matter in the end (although shorter class names mean shorter stylesheets) because the point is that they are dynamically generated, unique, and mapped to the correct styles.在使用CSS模块时,类名是动态生成的,唯一的,并准确对应到源文件中的各个类的样式。

这也是实现样式作用域的原理。它们被限定在特定的模板里。例如我们在buttons.js里引入buttons.css文件,并使用.btn的样式,在其他组件里是不会被.btn影响的,除非它也引入了buttons.css.

可我们是出于什么目的把CSS和HTML文件搞得这么零碎呢?我们为什么要使用CSS模块呢?

为什么我们需要CSS模块化

CSS全局作用域问题

CSS的规则都是全局的,任何一个组件的样式规则,都对整个页面有效。相信写css的人都会遇到样式冲突(污染)的问题。

于是一般这么做(笔者都做过):
* class命名写长一点吧,降低冲突的几率
* 加个父元素的选择器,限制范围
* 重新命名个class吧,比较保险

所以亟待解决的问题就是css局部作用域避免全局样式冲突(污染)的问题

JS CSS无法共享变量

太阳集团游戏,复杂组件要使用 JS 和 CSS 来共同处理样式,就会造成有些变量在 JS 和 CSS 中冗余,CSS预处理器/后处理器 等都不提供跨 JS 和 CSS 共享变量这种能力。

健壮并且扩展方便的CSS

作为有追求的工程师,编写健壮并且扩展方便的CSS一直是我们的目标。那么如何定义健壮并且扩展方便?有三个要点:

  • www.22138com,面向组件 – 处理 UI 复杂性的最佳实践就是将 UI 分割成一个个的小组件 Locality_of_reference 。如果你正在使用一个合理的框架,JavaScript 方面就将原生支持(组件化)。举个例子,React 就鼓励高度组件化和分割。我们希望有一个 CSS 架构去匹配。
  • 沙箱化(Sandboxed) – 如果一个组件的样式会对其他组件产生不必要以及意想不到的影响,那么将 UI 分割成组件并没有什么用。就这方面而言,CSS的全局作用域会给你造成负担。
  • 方便 – 我们想要所有好的东西,并且不想产生更多的工作。也就是说,我们不想因为采用这个架构而让我们的开发者体验变得更糟。可能的话,我们想开发者体验变得更好。

CSS模块化方案分类

CSS 模块化的解决方案有很多,但主要有三类。

CSS 命名约定

规范化CSS的模块化解决方案(比如BEM BEM — Block Element Modifier,OOCSS,AMCSS,SMACSS,SUITCSS)
但存在以下问题:
* JS CSS之间依然没有打通变量和选择器等
* 复杂的命名

CSS in JS

彻底抛弃 CSS,用 JavaScript 写 CSS 规则,并内联样式。 React: CSS in JS // Speaker Deck。Radium,react-style 属于这一类。但存在以下问题:
* 无法使用伪类,媒体查询等
* 样式代码也会出现大量重复。
* 不能利用成熟的 CSS 预处理器(或后处理器)

使用JS 来管理样式模块

使用JS编译原生的CSS文件,使其具备模块化的能力,代表是 CSS Modules GitHub – css-modules/css-modules: Documentation about css-modules 。

CSS Modules 能最大化地结合现有 CSS 生态(预处理器/后处理器等)和 JS 模块化能力,几乎零学习成本。只要你使用 Webpack,可以在任何项目中使用。是笔者认为目前最好的 CSS 模块化解决方案。

CSS Modules 使用教程

启用 CSS Modules

JavaScript

// webpack.config.js css?modules&localIdentName=[name]__[local]-[hash:base64:5]

1
2
// webpack.config.js
css?modules&localIdentName=[name]__[local]-[hash:base64:5]

加上 modules 即为启用,localIdentName 是设置生成样式的命名规则。

CSS

/* components/Button.css */ .normal { /* normal 相关的所有样式 */ }

1
2
/* components/Button.css */
.normal { /* normal 相关的所有样式 */ }

JavaScript

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

1
2
3
4
// components/Button.js
import styles from './Button.css';
console.log(styles);
buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

生成的 HTML 是

XHTML

阅读本文需要 11m 24s。<button class="button--normal-abc53">Submit</button>

1
<button class="button--normal-abc53">Submit</button>

注意到 button--normal-abc53 是 CSS Modules 按照 localIdentName 自动生成的 class 名。其中的abc53 是按照给定算法生成的序列码。经过这样混淆处理后,class 名基本就是唯一的,大大降低了项目中样式覆盖的几率。同时在生产环境下修改规则,生成更短的 class 名,可以提高 CSS 的压缩率。

上例中 console 打印的结果是:

CSS

Object {   normal: 'button--normal-abc53',   disabled: 'button--disabled-def886', }

1
2
3
4
Object {
  normal: 'button--normal-abc53',
  disabled: 'button--disabled-def886',
}

CSS Modules 对 CSS 中的 class 名都做了处理,使用对象来保存原 class 和混淆后 class 的对应关系。

通过这些简单的处理,CSS Modules 实现了以下几点:
* 所有样式都是局部作用域 的,解决了全局污染问题
* class 名生成规则配置灵活,可以此来压缩 class 名
* 只需引用组件的 JS 就能搞定组件所有的 JS 和 CSS
* 依然是 CSS,几乎 0 学习成本

CSS Modules 在React中的实践

那么我们在React中怎么使用?

手动引用解决

className 处直接使用 css 中 class 名即可。

JavaScript

import React from 'react'; import styles from './table.css';   export default class Table extends React.Component {     render () {         return <div className={styles.table}>             <div className={styles.row}>             </div>         </div>;     } }

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';
import styles from './table.css';
 
export default class Table extends React.Component {
    render () {
        return <div className={styles.table}>
            <div className={styles.row}>
            </div>
        </div>;
    }
}

渲染出来的组件出来

XHTML

<div class="table__table___32osj">     <div class="table__row___2w27N">     </div> </div>

1
2
3
4
<div class="table__table___32osj">
    <div class="table__row___2w27N">
    </div>
</div>

react-css-modules

如果你不想频繁的输入 styles.**,有一个 GitHub – gajus/react-css-modules: Seamless mapping of class names to CSS modules inside of React components.,它通过高阶函数的形式来生成className,不过不推荐使用,后文会提到。

API也很简单,给组件外包一个CSSModules即可。

JavaScript

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>;     } }   export default CSSModules(Table, styles);

1
2
3
4
5
6
7
8
9
10
11
12
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>;
    }
}
 
export default CSSModules(Table, styles);

不过这样我们可以看到,它是需要运行时的依赖,而且需要在运行时才获取className,性能损耗大,那么有没有方便又接近无损的方法呢?答案是有的,使用babel插件babel-plugin-react-css-modulesGitHub – gajus/babel-plugin-react-css-modules: Transforms styleName to className using compile time CSS module resolution. 把className获取前置到编译阶段。

babel-plugin-react-css-modules

babel-plugin-react-css-modules阅读本文需要 11m 24s。 可以实现使用styleName属性自动加载CSS模块。我们通过该babel插件来进行语法树解析并最终生成className

来看看组件的写法,现在你只需要把className换成styleName即可获得CSS局部作用域的能力了,是不是非常简单。

JavaScript

import React from 'react'; import styles from './table.css';   class Table extends React.Component {     render () {         return <div styleName='table'>         </div>;     } }   export default Table;

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';
import styles from './table.css';
 
class Table extends React.Component {
    render () {
        return <div styleName='table'>
        </div>;
    }
}
 
export default Table;

工作原理

那么该babel插件是怎么工作的呢?让我们从官方文档入手:

GitHub – gajus/babel-plugin-react-css-modules: Transforms styleName to className using compile time CSS module resolution.

笔者不才 ,稍作翻译如下:
1. 构建每个文件的所有样式表导入的索引(导入具有.css.scss扩展名的文件)。

  1. 使用postcss 解析匹配到的css文件
  2. 遍历所有 JSX 元素声明
  3. styleName 属性解析成匿名和命名的局部css模块引用
  4. 查找与CSS模块引用相匹配的CSS类名称:
    * 如果styleName的值是一个字符串字面值,生成一个字符串字面值。
    * 如果是JSXExpressionContainer,在运行时使用helper函数来构建如果styleName的值是一个jSXExpressionContainer, 使用辅助函数([getClassName]在运行时构造className值。
  5. 从元素上移除styleName属性。
    7. 将生成的className添加到现有的className值中(如果不存在则创建className属性)。

使用实例

在成熟的项目中,一般都会用到CSS预处理器或者后处理器。

这里以使用了stylusCSS预处理器为例子,我们来看下如何使用。

  • 安装依赖

Shell

npm install -save-dev sugerss babel-plugin-react-css-modules

1
npm install -save-dev sugerss babel-plugin-react-css-modules
  • 编写Webpack配置
JavaScript

// webpack.config.js module: {   loaders: [{     test: /\.js?$/,
    loader: [['babel-plugin-react-css-modules',{
          generateScopedName:'[name]__[local]',
          filetypes: {               ".styl": "sugerss"            }
     }]]   }, {     test: /\.module.styl$/,     loader:
'style!css?modules&localIdentName=[name]__[local]!styl?sourceMap=true'
  }, {     test: /\.styl$/,     loader:
'style!css!styl?sourceMap=true'   }] }

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-10">
10
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-11">
11
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-12">
12
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-13">
13
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-14">
14
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-15">
15
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-16">
16
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-17">
17
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-18">
18
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6729d9ed4116610999-1" class="crayon-line">
// webpack.config.js
</div>
<div id="crayon-5b8f6729d9ed4116610999-2" class="crayon-line crayon-striped-line">
module: {
</div>
<div id="crayon-5b8f6729d9ed4116610999-3" class="crayon-line">
  loaders: [{
</div>
<div id="crayon-5b8f6729d9ed4116610999-4" class="crayon-line crayon-striped-line">
    test: /.js?$/,
</div>
<div id="crayon-5b8f6729d9ed4116610999-5" class="crayon-line">
    loader: [['babel-plugin-react-css-modules',{
</div>
<div id="crayon-5b8f6729d9ed4116610999-6" class="crayon-line crayon-striped-line">
          generateScopedName:'[name]__[local]',
</div>
<div id="crayon-5b8f6729d9ed4116610999-7" class="crayon-line">
          filetypes: {
</div>
<div id="crayon-5b8f6729d9ed4116610999-8" class="crayon-line crayon-striped-line">
              &quot;.styl&quot;: &quot;sugerss&quot;
</div>
<div id="crayon-5b8f6729d9ed4116610999-9" class="crayon-line">
           }
</div>
<div id="crayon-5b8f6729d9ed4116610999-10" class="crayon-line crayon-striped-line">
     }]]
</div>
<div id="crayon-5b8f6729d9ed4116610999-11" class="crayon-line">
  }, {
</div>
<div id="crayon-5b8f6729d9ed4116610999-12" class="crayon-line crayon-striped-line">
    test: /.module.styl$/,
</div>
<div id="crayon-5b8f6729d9ed4116610999-13" class="crayon-line">
    loader: 'style!css?modules&amp;localIdentName=[name]__[local]!styl?sourceMap=true'
</div>
<div id="crayon-5b8f6729d9ed4116610999-14" class="crayon-line crayon-striped-line">
  }, {
</div>
<div id="crayon-5b8f6729d9ed4116610999-15" class="crayon-line">
    test: /.styl$/,
</div>
<div id="crayon-5b8f6729d9ed4116610999-16" class="crayon-line crayon-striped-line">
    loader: 'style!css!styl?sourceMap=true'
</div>
<div id="crayon-5b8f6729d9ed4116610999-17" class="crayon-line">
  }]
</div>
<div id="crayon-5b8f6729d9ed4116610999-18" class="crayon-line crayon-striped-line">
}
</div>
</div></td>
</tr>
</tbody>
</table>
  • 组件写法

JavaScript

import React from 'react'; import './table.module.styl';   class Table extends React.Component {     render () {         return <div styleName='table'>         </div>;     } }   export default Table;

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';
import './table.module.styl';
 
class Table extends React.Component {
    render () {
        return <div styleName='table'>
        </div>;
    }
}
 
export default Table;

如上,你可以通过配置Webpack中module.loaders的test路径Webpack-module-loaders-configuration,来区分样式文件是否需要CSS模块化。
搭配sugerss这个postcss插件作为stylus的语法加载器,来支持babel插件babel-plugin-react-css-modules的语法解析。

最后我们回过头来看下,我们React组件只需要把className换成styleName,搭配以上构建配置,即可实现CSS模块化 。

最后

CSS Modules 很好的解决了 CSS 目前面临的模块化难题。支持与 CSS处理器搭配使用,能充分利用现有技术积累。如果你的产品中正好遇到类似问题,非常值得一试。

希望大家都能写出健壮并且可扩展的CSS,以上。

1 赞 2 收藏 评论

www.22138com 2

TAG标签: www.22138com CSS
版权声明:本文由太阳集团发布于太阳2007娱乐官方网址,转载请注明出处:阅读本文需要 11m 24s