未来的编码格局

CSS Modules 详解及 React 中实践

2016/01/18 · CSS · CSS
Modules,
React

原文出处: pure render –
camsong   

亚洲必赢官网 1

CSS 是前者领域中前进最慢的一块。由于 ES2015/2016 的很快普及和
Babel/Webpack 等工具的迅猛发展,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 模块化能力,API
简洁到大约零读书开支。公布时照旧编译出单身的 JS 和 CSS。它并不器重于
React,只要你使用 Webpack,可以在 Vue/Angular/jQuery
中利用。是自身觉着当下最好的 CSS
模块化解决方案。如今在类型中大批量选取,下面具体享受下进行中的细节和想法。

 

CSS Modules 入门及 React 中实践

2017/03/25 · CSS ·
React

原稿出处:
AlloyTeam   

前言

那是Glen
Maddern公布于二〇一五年五月19日的一篇小说,紧假使从前翻译的稿子《知情CSS模块方法》里提到那篇文章,现在算是顺藤摸瓜跟进来看看。

此间的翻译都是基于我要好的知道举行的,所以不是一句一句的来的,有怎样不对的也未免,水平有限,希望大家提议。

前言

那是Glen
Maddern发表于二零一五年五月19日的一篇小说,重倘诺事先翻译的篇章《了然CSS模块方法》里关系那篇文章,现在毕竟顺藤摸瓜跟进来看看。

此处的翻译都是根据自己要好的知情举办的,所以不是一句一句的来的,有啥不对的也难免,水平有限,希望大家提议。

CSS 模块化蒙受了什么难题?

CSS 模块化主要的是要化解好八个难题:CSS
样式的导入和导出。灵活按需导入以便复用代码;导出时要力所能及隐藏其中功用域,防止导致全局污染。Sass/Less/PostCSS
等后续试图缓解 CSS
编程能力弱的题材,结果它们做的也着实美丽,但那并不曾缓解模块化最要紧的难题。非死不可工程师 Vjeux 首先抛出了 React 开发中遭遇的一名目繁多 CSS
相关题材。加上自身个人的眼光,总括如下:

  1. 全局污染

CSS
使用全局拔取器机制来安装样式,优点是有利重写样式。缺点是装有的体制都是全局生效,样式可能被指鹿为马覆盖,由此爆发了极度难看的
!important,甚至 inline !important未来的编码格局。
和错综复杂的[选用器权重计数表](Selectors Level
3),进步犯错几率和采用资金。Web
Components 标准中的 Shadow DOM
能彻底解决那些题目,但它的做法有些极端,样式彻底局地化,造成外部无法重写样式,损失了灵活性。

  1. 取名混乱

 

由于全局污染的题材,三个人同台开发时为了防止样式争持,选用器越来越复杂,不难形成差别的命名风格,很难统一。样式变多后,命名将尤其混乱。

  1. 借助于管理不彻底

零件应该相互独立,引入一个零件时,应该只引入它所急需的 CSS
样式。但后天的做法是除了要引入 JS,还要再引入它的 CSS,而且 Saas/Less
很难落到实处对每个组件都编译出单身的 CSS,引入所有模块的 CSS 又导致浪费。JS
的模块化已经极度干练,借使能让 JS 来保管 CSS
依赖是很好的解决办法。Webpack 的 css-loader 提供了那种力量。

  1. 心慌意乱共享变量

复杂组件要运用 JS 和 CSS 来共同处理体制,就会导致有些变量在 JS 和 CSS
中冗余,Sass/PostCSS/CSS 等都不提供跨 JS 和 CSS 共享变量那种能力。

  1. 代码压缩不到底

由于移动端网络的不确定性,现在对 CSS
压缩已经到了变态的程度。很多压缩工具为了省去一个字节会把 ’16px’ 转成
‘1pc’。但对万分长的 class 名却力不从心,力没有用到刀刃上。

地点的题材如若只凭 CSS 自身是无法化解的,若是是透过 JS 来治本 CSS
就很好解决,因而 Vjuex 给出的化解方案是一点一滴的 CSS in
JS,但这一定于完全抛弃CSS,在 JS 中以 Object 语法来写
CSS,臆度刚看到的小伙伴都震惊了。直到出现了 CSS Modules。

 

写在面前

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

亚洲必赢官网 2

开卷本文要求 11m 24s。

正文

若是想在新近CSS开发考虑上找到一个生成点,最好去找克里Stowe弗 Chedeau
二〇一四年八月在NationJS上刊出的“css in
js”解说。那是一个分界线,各样分裂的合计,似乎高速粒子似的在自己的大势上急速前进。例如:在React及片段信赖React的项目中写样式,
React
Style,jsxstyle和Radium是里面八个,最新的,最高明的,和最得力的艺术。假设发明是在一种探索的情形下邻座的可能(adjacent
possible),那么christopher是创办了比比皆是好像附近(adjacent)可能性。

亚洲必赢官网 3

那些标题,以分裂的款式存在于大的CSS代码库中。christopher提议,那一个题材都可能通过在js中写代码来化解。但那种解决方案引入了其自身的纷纷和特征。只要看一下,在前面提到的品种中(React
Style,jsxstyle和Radium),处理在:hover状态下range的主意。这些标题,在浏览器端css中早已早被解决了。

CSS Modules
team找到难题的要紧–保持和CSS一致,使用styles-in-js的不二法门编写。就算我们仍然百折不挠主张使用了CSS的款式,但还有要感谢对大家提供比比皆是提议的爱侣。

大家直接在费尽脑筋地思考CSS,怎么样去编写更好。

正文

万一想在不久前CSS开发考虑上找到一个变型点,最好去找克里斯多夫 Chedeau
二〇一四年十一月在NationJS上刊载的“css in
js”演说。那是一个分界线,种种不相同的系念,就像是高速粒子似的在融洽的来头上飞快前进。例如:在React及一些看重React的项目中写样式,
React
Style,jsxstyle和Radium是其中多个,最新的,最高明的,和最可行的方式。即便发明是在一种探索的事态下邻座的或许(adjacent
possible),那么christopher是创办了好多近乎附近(adjacent)可能性。

亚洲必赢官网 4

那些难题,以不一致的款式存在于大的CSS代码库中。christopher提出,那些题材都可能通过在js中写代码来缓解。但那种解决方案引入了其本身的复杂和特性。只要看一下,在从前提到的花色中(React
Style,jsxstyle和Radium),处理在:hover状态下range的措施。那么些标题,在浏览器端css中已经早被解决了。

CSS Modules
team找到标题标重中之重–保持和CSS一致,使用styles-in-js的点子编写。就算大家仍旧坚贞不屈主张使用了CSS的花样,但还有要谢谢对大家提供许多提议的恋人。

我们直接在搜索枯肠地思索CSS,怎样去编写更好。

CSS Modules 模块化方案

亚洲必赢官网 5

CSS Modules 内部通过 [ICSS](css-modules/icss ·
GitHub)
来化解体制导入和导出那五个难点。分别对应 :import:export
四个新增的伪类。

JavaScript

:import(“path/to/dep.css”) { localAlias: keyFromDep; /* … */ }
:export { exportedKey: exportedValue; /* … */ }

1
2
3
4
5
6
7
8
:import("path/to/dep.css") {
  localAlias: keyFromDep;
  /* … */
}
:export {
  exportedKey: exportedValue;
  /* … */
}

 

但一贯动用那七个至关主要字编程太坚苦,实际项目中很少会从来利用它们,大家要求的是用
JS 来治本 CSS 的力量。结合 Webpack 的 css-loader 后,就可以在 CSS
中定义样式,在 JS 中导入。
启用 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 是安装生成样式的命名规则。

JavaScript

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

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

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 是

<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 打印的结果是:

JavaScript

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 完结了以下几点:

  • 负有样式都是 local 的,解决了命名冲突和大局污染难题
  • class 名生成规则配置灵活,可以此来裁减 class 名
  • 只需引用组件的 JS 就能搞定组件所有的 JS 和 CSS
  • 依然是 CSS,几乎 0 学习成本

体制默许局地

应用了 CSS Modules 后,就一定于给各种 class 名外加加了一个
:local,以此来完结样式的局地化,假若您想切换来全局情势,使用相应的
:global

:local:global 的界别是 CSS Modules 只会对 :local 块的 class
样式做 localIdentName 规则处理,:global 的样式编译后不变。

JavaScript

.normal { color: green; } /* 以上与下部等价 */ :local(.normal) {
color: green; } /* 定义全局样式 */ :global(.btn) { color: red; } /*
定义三个全局样式 */ :global { .link { color: green; } .box { color:
yellow; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.normal {
  color: green;
}
 
/* 以上与下面等价 */
:local(.normal) {
  color: green;
}
 
/* 定义全局样式 */
:global(.btn) {
  color: red;
}
 
/* 定义多个全局样式 */
:global {
  .link {
    color: green;
  }
  .box {
    color: yellow;
  }
}

Compose 来构成样式

对此样式复用,CSS Modules 只提供了唯一的法子来拍卖:composes 组合

JavaScript

/* components/Button.css */ .base { /* 所有通用的样式 */ } .normal {
composes: base; /* normal 其余样式 */ } .disabled { composes: base;
/* disabled 别的样式 */ }

1
2
3
4
5
6
7
8
9
10
11
12
/* components/Button.css */
.base { /* 所有通用的样式 */ }
 
.normal {
  composes: base;
  /* normal 其它样式 */
}
 
.disabled {
  composes: base;
  /* disabled 其它样式 */
}

JavaScript

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

1
2
3
import styles from ‘./Button.css’;
 
buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

生成的 HTML 变为

<button class=”button–base-fec26
button–normal-abc53″>Submit</button>

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

由于在 .normal 中 composes 了 .base,编译后会 normal 会变成多个class。

composes 还是能构成外部文件中的样式。

JavaScript

/* settings.css */ .primary-color { color: #f40; } /*
components/Button.css */ .base { /* 所有通用的体裁 */ } .primary {
composes: base; composes: primary-color from ‘./settings.css’; /*
primary 此外样式 */ }

1
2
3
4
5
6
7
8
9
10
11
12
13
/* settings.css */
.primary-color {
  color: #f40;
}
 
/* components/Button.css */
.base { /* 所有通用的样式 */ }
 
.primary {
  composes: base;
  composes: primary-color from ‘./settings.css’;
  /* primary 其它样式 */
}

 

对于一大半品类,有了 composes 后早就不复要求Sass/Less/PostCSS。但倘使你想用的话,由于 composes 不是专业的 CSS
语法,编译时会报错。就只好动用预处理器自己的语法来做样式复用了。
class 命名技巧

CSS Modules 的命名规范是从 BEM 扩张而来。BEM 把体制名分为 3
个级别,分别是:

  • Block:对应模块名,如 Dialog
  • Element:对应模块中的节点名 Confirm Button
  • Modifier:对应节点相关的动静,如 disabled、highlight

综上,BEM 最后赢得的 class 名为
dialog__confirm-button--highlight。使用双符号 __--
是为着和区块内单词间的相间符区分开来。尽管看起来有些出人意料,但 BEM
被尤其多的大型项目和团协会利用。大家履行下来也很认可那种命有名的模特式。

CSS Modules 中 CSS 文件名正要对应 Block 名,只须要再考虑 Element 和
Modifier。BEM 对应到 CSS Modules 的做法是:

JavaScript

/* .dialog.css */ .ConfirmButton–disabled { /* … */ }

1
2
3
4
/* .dialog.css */
.ConfirmButton–disabled {
  /* … */
}

你也可以不依据完全的命名规范,使用 camelCase 的写法把 Block 和 Modifier
放到一起:

JavaScript

/* .dialog.css */ .disabledConfirmButton { }

1
2
3
/* .dialog.css */
.disabledConfirmButton {
}

哪些促成CSS,JS变量共享

注:CSS Modules 中从未变量的概念,这里的 CSS 变量指的是 Sass 中的变量。

下边提到的 :export 关键字可以把 CSS 中的 变量输出到 JS
中。下边演示怎样在 JS 中读取 Sass 变量:

JavaScript

/* config.scss */ $primary-color: #f40; :export { primaryColor:
$primary-color; }

1
2
3
4
5
6
/* config.scss */
$primary-color: #f40;
 
:export {
  primaryColor: $primary-color;
}

 

JavaScript

/* app.js */ import style from ‘config.scss’; // 会输出 #F40
console.log(style.primaryColor);

1
2
3
4
5
/* app.js */
import style from ‘config.scss’;
 
// 会输出 #F40
console.log(style.primaryColor);

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模块呢?

第1步:默许局地效能域

在css模块中,每一个文件都是独自编译的,由此你可以行使一些CSS短命名-不用担心命名冲突。上边看一下,提交按钮的4种情状的例

亚洲必赢官网 6

第1步:默许局地功效域

在css模块中,每一个文本都是独立编译的,由此你可以使用部分CSS短命名-不用担心命名争论。上边看一下,提交按钮的4种情形的例

亚洲必赢官网 7

亚洲必赢官网 ,CSS Modules 使用技巧

CSS Modules 是对现有的 CSS
做减法。为了追求**不难可控**,小编提出按照如下原则:

  • 不应用拔取器,只利用 class 名来定义样式
  • 不层叠八个 class,只利用一个 class 把拥有样式定义好
  • 不嵌套
  • 使用 composes 组合来兑现复用

上边两条规则相当于削弱了体制中最灵敏的有些,初使用者很难接受。第一条实施起来难度不大,但第二条如若模块状态过多时,class
数量将倍加上涨。

自然要明白,上面之所以称之为指出,是因为 CSS Modules
并不强制你一定要那样做。听起来有些格格不入,由于多数 CSS
项目存在深厚的野史遗留难题,过多的限定就象征增添迁移费用和与表面同盟的资金。初期使用中毫无疑问要求一些和平解决。幸运的是,CSS
Modules 这一点做的很好:

1. 假如自己对一个因素选择八个 class 呢?

没难点,样式依然生效。

2. 怎么自身在一个 style 文件中应用同名 class 呢?

没问题,这么些同名 class 编译后尽管可能是随机码,但仍是同名的。

3. 若是自己在 style 文件中应用了 id 选取器,伪类,标签接纳器等啊?

没难点,所有那些接纳器将不被转移,原封不动的面世在编译后的 css
中。也就是说 CSS Modules 只会变换 class 名相关样式。

但注意,上面 3 个“要是”尽量不要暴发

为什么我们须求CSS模块化

好端端的CSS书写格局

用Suit或BEM命名、一些CSS样式、一段html。代码如下:

css代码段:

/* components/submit-button.css */

.Button { /* all styles for Normal */ }

.Button–disabled { /* overrides for Disabled */ }

.Button–error { /* overrides for Error */ }

.Button–in-progress { /* overrides for In Progress */

html代码段:

<button class=”Button
Button–in-progress”>Processing…</button>

位置代码运行不错,大家有4种情形的类名,BEM命名,幸免了选拔嵌套选拔器。使用大写字母发轫的单词Button用作选择器,防止与事先或引用样式的类名争辨。并且大家拔取–modifier语法来解除基础样式。

到现行截止,这都是一段不错的可保证的代码。但也引入了严俊的命名规范。但这也是能用标准CSS,做到的最好的点子了。

例行的CSS书写格局

用Suit或BEM命名、一些CSS样式、一段html。代码如下:

css代码段:

/* components/submit-button.css */

.Button { /* all styles for Normal */ }

.Button–disabled { /* overrides for Disabled */ }

.Button–error { /* overrides for Error */ }

.Button–in-progress { /* overrides for In Progress */

html代码段:

<button class=”Button
Button–in-progress”>Processing…</button>

下边代码运行不错,大家有4种景况的类名,BEM命名,防止了选取嵌套接纳器。使用大写字母开头的单词Button作为选拔器,幸免与事先或引用样式的类名争论。并且大家选用–modifier语法来驱除基础样式。

到明日长逝,那都是一段不错的可有限帮衬的代码。但也引入了严谨的命名规范。但那也是能用标准CSS,做到的最好的艺术了。

CSS Modules 结合 React 实践

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

JavaScript

.root {} .confirm {} .disabledConfirm {}

1
2
3
.root {}
.confirm {}
.disabledConfirm {}

import classNames from ‘classnames’; import styles from ‘./dialog.css’;
export default class Dialog extends React.Component { render() { const
cx = classNames({ confirm: !this.state.disabled, disabledConfirm:
this.state.disabled }); return <div className={styles.root}> <a
className={styles.disabledConfirm}>Confirm</a> … </div>
} }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import classNames from ‘classnames’;
import styles from ‘./dialog.css’;
 
export default class Dialog extends React.Component {
  render() {
    const cx = classNames({
      confirm: !this.state.disabled,
      disabledConfirm: this.state.disabled
    });
 
    return <div className={styles.root}>
      <a className={styles.disabledConfirm}>Confirm</a>
      …
    </div>
  }
}

专注,一般把组件最外层节点对应的 class 名称为 root。那里运用了
[classnames](https://www.npmjs.com/package/classnames)
库来操作 class 名。

要是您不想频仍的输入 styles.**,能够试一下
[react-css-modules](gajus/react-css-modules ·
GitHub),它经过高阶函数的款型来防止重复输入
styles.**

CSS Modules 结合历史遗留项目推行

好的技艺方案除了效能强大炫酷,还要能完毕现有项目能平滑迁移。CSS Modules
在那或多或少上表现的卓殊灵活。

外表怎么着覆盖局地样式

当生成混淆的 class 名后,可以缓解命名争论,但因为不可能预感最后 class
名,无法经过一般选用器覆盖。咱们现在项目中的实践是足以给组件关键节点加上
data-role 属性,然后通过品质选拔器来覆盖样式。

// dialog.js return <div className={styles.root}
data-role=’dialog-root’> <a className={styles.disabledConfirm}
data-role=’dialog-confirm-btn’>Confirm</a> … </div>

1
2
3
4
5
// dialog.js
  return <div className={styles.root} data-role=’dialog-root’>
      <a className={styles.disabledConfirm} data-role=’dialog-confirm-btn’>Confirm</a>
      …
  </div>

 

JavaScript

/* dialog.css */ [data-role=”dialog-root”] { // override style }

1
2
3
4
/* dialog.css */
[data-role="dialog-root"] {
  // override style
}

因为 CSS Modules 只会生成类拔取器,所以那里的质量采取器不需求添加
:global

怎么着与全局样式共存

前者项目不可幸免会引入 normalize.css 或其余一类全局 css 文件。使用
Webpack 可以让全局样式和 CSS Modules
的有的样式和谐共存。上面是我们项目中拔取的 webpack 部分布置代码:

JavaScript

作品权归小编所有。 商业转发请联系小编得到授权,非商业转发请注脚出处。
作者:camsong 链接:
来源:知乎 // webpack.config.js 局部 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’ }] }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:camsong
链接:http://zhuanlan.zhihu.com/purerender/20495964
来源:知乎
 
// webpack.config.js 局部
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’
  }]
}

JavaScript

/* src/app.js */ import ‘./styles/app.scss’; import Component from
‘./view/Component’ /* src/views/Component.js */ // 以下为组件相关样式
import ‘./Component.scss’;

1
2
3
4
5
6
7
/* src/app.js */
import ‘./styles/app.scss’;
import Component from ‘./view/Component’
 
/* src/views/Component.js */
// 以下为组件相关样式
import ‘./Component.scss’;

目录结构如下:

JavaScript

src ├── app.js ├── styles │ ├── app.scss │ └── normalize.scss └── views
├── Component.js └── Component.scss

1
2
3
4
5
6
7
8
src
├── app.js
├── styles
│   ├── app.scss
│   └── normalize.scss
└── views
    ├── Component.js
    └── Component.scss

如此所有全局的体裁都放到 src/styles/app.scss
中引入就足以了。其余具有目录包涵 src/views 中的样式都是部分的。

CSS全局效能域难题

CSS的条条框框都是大局的,任何一个组件的样式规则,都对所有页面有效。相信写css的人都会遇见样式顶牛(污染)的难题。

于是乎一般这么做(作者都做过):
* class命名写长一点吗,下落争持的几率
* 加个父元素的选取器,限制范围
* 重新命名个class吧,比较有限支撑

就此亟待解决的难题就是css局地效能域防止全局样式争执(污染)的标题

CSS模块书写格局

应用CSS模块,你不用担心使用一些短命名了。可以像上面那样。

/* components/submit-button.css */

.normal { /* all styles for Normal */ }

.disabled { /* all styles for Disabled */ }

.error { /* all styles for Error */ }

.inProgress { /* all styles for In Progress */

看,你不要在其余地点再去加长长的前缀。为何能够那样做,大家得以像其它语言一样,不用在地头变量前加长长的前缀,只要把CSS对应的公文名改成submit-botton.css

那足以让在JS中动用requireimport加载的CSS模块文件,可以被编译出来。

/* components/submit-button.js */

import styles from ‘./submit-button.css’;

buttonElem.outerHTML = `<button
class=${styles.normal}>Submit</button>`

确实在页面使用的体制名,是动态变化的绝无仅有标识。CSS模块把文件编译成ICSS格式的文本,那种格式文件可以方便CSS和JS举行通讯。当您运行程序,会取得近似上边的代码

<button class=”components_submit_button__normal__abc5436″>
Processing…</button>

取得近似结果,表达运行成功~

CSS模块书写方式

动用CSS模块,你不要顾虑使用一些短命名了。可以像上边那样。

/* components/submit-button.css */

.normal { /* all styles for Normal */ }

.disabled { /* all styles for Disabled */ }

.error { /* all styles for Error */ }

.inProgress { /* all styles for In Progress */

看,你不用在任什么地点方再去加长长的前缀。为何可以这么做,大家得以像任何语言一样,不用在本地变量前加长长的前缀,只要把CSS对应的公文名改成submit-botton.css

那足以让在JS中利用requireimport加载的CSS模块文件,可以被编译出来。

/* components/submit-button.js */

import styles from ‘./submit-button.css’;

buttonElem.outerHTML = `<button
class=${styles.normal}>Submit</button>`

确实在页面使用的体裁名,是动态变化的绝无仅有标识。CSS模块把文件编译成ICSS格式的文本,那种格式文件可以便宜CSS和JS举行通讯。当您运行程序,会赢得近似上面的代码

<button class=”components_submit_button__normal__abc5436″>
Processing…</button>

获取近似结果,表达运行成功~

总结

CSS Modules 很好的解决了 CSS 近年来边临的模块化难点。匡助与
Sass/Less/PostCSS
等搭配使用,能充足利用现有技术积淀。同时也能和全局样式灵活搭配,便于项目中日渐搬迁至
CSS Modules。CSS Modules
的落到实处也属轻量级,以后有专业解决方案后方可低本钱迁移。如若您的出品中正好遇到类似题材,万分值得一试。

1 赞 2 收藏
评论

亚洲必赢官网 8

JS CSS不能共享变量

复杂组件要动用 JS 和 CSS 来共同处理体制,就会招致有些变量在 JS 和 CSS
中冗余,CSS预处理器/后处理器 等都不提供跨 JS 和 CSS 共享变量那种能力。

取名约定

要么拿按钮的例证来说

/* components/submit-button.css */

.normal { /* all styles for Normal */ }

.disabled { /* all styles for Disabled */ }

.error { /* all styles for Error */ }

.inProgress { /* all styles for In Progress */

具备类名都是单独的,不是一个是基类名,其余的用来修改。在CSS模块中,所有类必须概括所有的品质和体制。那让你在JS中选用类名时有很大的不比。

/* 不要像那样 */

`class=${[styles.normal, styles[‘in-progress’]].join(” “)}`

/* 差别之处是运用单独的类名 */

`class=${styles[‘in-progress’]}`

/* 最好应用驼峰式 */

`class=${styles.inProgress}`

理所当然,若是您是按照代码量来收钱的,你可以按照你的办法持续。

命名约定

或者拿按钮的例证来说

/* components/submit-button.css */

.normal { /* all styles for Normal */ }

.disabled { /* all styles for Disabled */ }

.error { /* all styles for Error */ }

.inProgress { /* all styles for In Progress */

所有类名都是独立的,不是一个是基类名,其它的用来修改。在CSS模块中,所有类必须概括富有的性质和体制。那让你在JS中运用类名时有很大的不等。

/* 不要像这么 */

`class=${[styles.normal, styles[‘in-progress’]].join(” “)}`

/* 分化之处是运用单独的类名 */

`class=${styles[‘in-progress’]}`

/* 最好应用驼峰式 */

`class=${styles.inProgress}`

当然,倘使你是依据代码量来收钱的,你可以按照你的法子持续。

年富力强并且扩大方便的CSS

作为有追求的工程师,编写健壮并且扩大方便的CSS一贯是我们的靶子。那么如何定义健壮并且增加方便?有多个要点:

  • 面向组件 – 处理 UI 复杂性的特等实践就是将 UI 分割成一个个的小组件
    Locality_of_reference
    。若是您正在采用一个客观的框架,JavaScript
    方面就将原生援助(组件化)。举个例子,React
    就鼓励中度组件化和分叉。大家期望有一个 CSS 架构去匹配。
  • 沙箱化(Sandboxed) –
    如果一个零件的样式会对其他零件发生不须要以及意外的震慑,那么将
    UI
    分割成组件并没有怎么用。就那地点而言,CSS的全局意义域会给你造成负担。
  • 造福 –
    大家想要所有好的东西,并且不想发生越多的劳作。也就是说,大家不想因为运用这些架构而让我们的开发者体验变得更糟。可能的话,咱们想开发者体验变得更好。

一个React例子

那里不是关于React特有的CSS模块。但React提供了,在行使CSS模块时,更加美好的体会。下边做一个复杂点的例子。

/* components/submit-button.jsx */

import { Component } from ‘react’;

import styles from ‘./submit-button.css’;

export default class SubmitButton extends Component {

render() {

let className, text = “Submit”

if (this.props.store.submissionInProgress) {

className = styles.inProgress text = “Processing…”

} else if (this.props.store.errorOccurred) {

className = styles.error

} else if (!this.props.form.valid) {

className = styles.disabled

} else {

className = styles.normal

}

return <button className={className}>{text}</button>

}

}

你可以采取你的体制,不用再想不开全局冲突,让你可以小心于组件开发,而不是在写样式上。一旦离开在此以前的数次在CSS,js之间切换方式,你就再也不想回到了。

但那只是开头,当您考虑体制统一时,CSS模块又万般无奈使用了。

一个React例子

此间不是有关React特有的CSS模块。但React提供了,在使用CSS模块时,越发优良的经验。上面做一个复杂点的例子。

/* components/submit-button.jsx */

import { Component } from ‘react’;

import styles from ‘./submit-button.css’;

export default class SubmitButton extends Component {

render() {

let className, text = “Submit”

if (this.props.store.submissionInProgress) {

className = styles.inProgress text = “Processing…”

} else if (this.props.store.errorOccurred) {

className = styles.error

} else if (!this.props.form.valid) {

className = styles.disabled

} else {

className = styles.normal

}

return <button className={className}>{text}</button>

}

}

您可以行使你的体裁,不用再担心全局争辩,让您可以小心于组件开发,而不是在写样式上。一旦离开以前的屡屡在CSS,js之间切换格局,你就再也不想回去了。

但那只是开头,当你着想体制统一时,CSS模块又无奈使用了。

CSS模块化方案分类

CSS 模块化的化解方案有无数,但要害有三类。

第2步 一切皆为组件

面前提到CSS模块要求每种状态都带有所有所需的体裁。

那边假若你必要多少个情形,大家相比较一下CSS模块和BEM命名。

/* BEM Style */

innerHTML = `<button class=”Button Button–in-progress”>`

/* CSS Modules */

innerHTML = `<button class=”${styles.inProgress}”>`

等一下,怎样在有着情形共享样式呢?答案是CSS模块的最强大工具-组件

.common { /* all the common styles you want */ }

.normal { composes: common; /* anything that only applies to Normal
*/ }

.disabled { composes: common; /* anything that only applies to
Disabled */ }

.error { composes: common; /* anything that only applies to Error */
}

.inProgress { composes: common; /* anything that only applies to In
Progress */ }

关键词composes指出.normal包含.common中的样式,就如sass里的@extend重点词一样。sass是经过重写css选用器来完成的。css模块则是透过改动js中动用的类名来落到实处。

第2步 一切皆为组件

眼前提到CSS模块须求每种状态都富含所有所需的体制。

这里假使你必要七个状态,大家相比较一下CSS模块和BEM命名。

/* BEM Style */

innerHTML = `<button class=”Button Button–in-progress”>`

/* CSS Modules */

innerHTML = `<button class=”${styles.inProgress}”>`

等一下,怎么着在颇具景况共享样式呢?答案是CSS模块的最有力工具-组件

.common { /* all the common styles you want */ }

.normal { composes: common; /* anything that only applies to Normal
*/ }

.disabled { composes: common; /* anything that only applies to
Disabled */ }

.error { composes: common; /* anything that only applies to Error */
}

.inProgress { composes: common; /* anything that only applies to In
Progress */ }

关键词composes指出.normal包含.common中的样式,就好像sass里的@extend重视词一样。sass是通过重写css接纳器来完成的。css模块则是经过变更js中应用的类名来落实。

CSS 命名约定

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

SASS:

行使前边的BEM例子,使用部分SASS的@extend

.Button–common { /* font-sizes, padding, border-radius */ }

.Button–normal { @extends .Button–common; /* blue color, light blue
background */}

.Button–error { @extends .Button–common; /* red color, light red
background */}

那将编译为

.Button–common, .Button–normal, .Button–error { /* font-sizes,
padding, border-radius */ }

.Button–normal { /* blue color, light blue background */ }

.Button–error { /* red color, light red background */ }

你只须求在您的标签上引用一个类名,能够赢得通用的和独有的样式。成效很有力,但您不可能不清楚,那也存在着新鲜情状和陷阱。HugoGiraudel
汇总了一些标题,想询问更加多,请点击《怎么你应当幸免采纳SASS的@extend》

SASS:

运用前边的BEM例子,使用一些SASS的@extend

.Button–common { /* font-sizes, padding, border-radius */ }

.Button–normal { @extends .Button–common; /* blue color, light blue
background */}

.Button–error { @extends .Button–common; /* red color, light red
background */}

那将编译为

.Button–common, .Button–normal, .Button–error { /* font-sizes,
padding, border-radius */ }

.Button–normal { /* blue color, light blue background */ }

.Button–error { /* red color, light red background */ }

你只须求在你的价签上引用一个类名,可以博得通用的和独有的体制。成效很有力,但您不可能不精通,那也设有着奇异意况和陷阱。HugoGiraudel
汇总了一些标题,想明白越多,请点击《为何你应有幸免选择SASS的@extend》

CSS in JS

彻底扬弃 CSS,用 JavaScript 写 CSS 规则,并内联样式。 React: CSS in JS
// Speaker
Deck。Radium,react-style
属于这一类。但存在以下难点:
* 不可能运用伪类,媒体询问等
* 样式代码也会冒出大量双重。
* 不可以运用成熟的 CSS 预处理器(或后电脑)

使用CSS模块

composes重中之重词和@extend选用办法类似,但做事方法是例外的。看个例子

.common { /* font-sizes, padding, border-radius */ }

.normal { composes: common; /* blue color, light blue background */
}

.error { composes: common; /* red color, light red background */ }

在浏览器上校会被编译为

.components_submit_button__common__abc5436 { /* font-sizes,
padding, border-radius */ }

.components_submit_button__normal__def6547 { /* blue color,
light blue background */ }

.components_submit_button__error__1638bcd { /* red color, light
red background */ }

在js代码中,import styles from “./submit-button.css”将得到

styles: {
common: “components_submit_button__common__abc5436”,
normal: “components_submit_button__common__abc5436
components_submit_button__normal__def6547”, error:
“components_submit_button__common__abc5436
components_submit_button__error__1638bcd”
}

要么采用styles.normalstryles.error,在DOM中校被渲染为五个类名

<button class=”components_submit_button__common__abc5436
components_submit_button__normal__def6547″>
Submit</button>

这就是composes的功用,你可以统一七个样式,但不用去修改你的JS代码,也不会重写你的CSS接纳器。

使用CSS模块

composes首要词和@extend应用方法类似,但工作方法是见仁见智的。看个例证

.common { /* font-sizes, padding, border-radius */ }

.normal { composes: common; /* blue color, light blue background */
}

.error { composes: common; /* red color, light red background */ }

在浏览器少校会被编译为

.components_submit_button__common__abc5436 { /* font-sizes,
padding, border-radius */ }

.components_submit_button__normal__def6547 { /* blue color,
light blue background */ }

.components_submit_button__error__1638bcd { /* red color, light
red background */ }

在js代码中,import styles from “./submit-button.css”将得到

styles: {
common: “components_submit_button__common__abc5436”,
normal: “components_submit_button__common__abc5436
components_submit_button__normal__def6547”, error:
“components_submit_button__common__abc5436
components_submit_button__error__1638bcd”
}

如故采取styles.normalstryles.error,在DOM元帅被渲染为四个类名

<button class=”components_submit_button__common__abc5436
components_submit_button__normal__def6547″>
Submit</button>

这就是composes的作用,你可以统一四个样式,但不用去修改你的JS代码,也不会重写你的CSS接纳器。

动用JS 来治本体制模块

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

CSS Modules 能最大化地整合现有 CSS 生态(预处理器/后电脑等)和 JS
模块化能力,大约零读书花费。只要你选择Webpack,可以在其他类型中应用。是小编认为眼前最好的 CSS 模块化解决方案。

第3步.文件间共享代码

使用SASS或LESS工作,通过@import来引用同一个工作空间的文件。你可以表明变量,函数,并在其他文件中利用。很科学的法子,但在挨家挨户不一样的门类中,变量命名有可能争论。那么你就得重构你的代码,编写如variables.scsssettings.scss,你也不知底怎么组件看重于如何个变量了。你的settings文件会变得很大。

也有更好的化解方案(《行使Webpack营造更小巧的CSS》),但出于SASS的全局属性,依旧有很大的限定。

CSS模块两次只运行一个独门的文件,因而不会传染全局成效域。js代码用利用importrequire来引用器重,CSS模块使用compose从另一个文书引用样式。

/* colors.css */

.primary { color: #720; }

.secondary { color: #777; }/* other helper classes… */

/* submit-button.css */

.common { /* font-sizes, padding, border-radius */ }

.normal { composes: common; composes: primary from
“../shared/colors.css”; }

利用组件,大家得以像引用本地类名一样,引用colors.css文本的类。而且,组件变化的类名在输出时会被改动,但CSS文件本身并不成形,composes块也会在转变浏览器端CSS之前被去除。

/* colors.css */
.shared_colors__primary__fca929 { color: #720; }
.shared_colors__secondary__acf292 { color: #777; }

/* submit-button.css */
.components_submit_button__common__abc5436 { /* font-sizes,
padding, border-radius */ }
.components_submit_button__normal__def6547 {}

 

<button class=”shared_colors__primary__fca929
components_submit_button__common__abc5436
components_submit_button__normal__def6547″> Submit
</button>

 

实际上,在浏览器端,normal没有我的体制。这是好工作,你可以添加新的语义化的目的,但不用去添加CSS样式。我们还是可以做得越来越多一点,

在全站开发中追加类名和视觉的一致性,在浏览器端裁减体制代码的轻重缓急。

旁注:可以使用csso检测并移除空类。

第3步.文件间共享代码

使用SASS或LESS工作,通过@import来引用同一个工作空间的公文。你可以注解变量,函数,并在其余文件中应用。很不错的法子,但在各种分裂的项目中,变量命名有可能冲突。那么您就得重构你的代码,编写如variables.scsssettings.scss,你也不知晓哪些组件依赖于如何个变量了。你的settings文件会变得很大。

也有更好的缓解方案(《运用Webpack创设更精致的CSS》),但由于SASS的大局属性,仍然有很大的限定。

CSS模块四回只运行一个独自的公文,由此不会污染全局成效域。js代码用利用importrequire来引用信赖,CSS模块使用compose从另一个文本引用样式。

/* colors.css */

.primary { color: #720; }

.secondary { color: #777; }/* other helper classes… */

/* submit-button.css */

.common { /* font-sizes, padding, border-radius */ }

.normal { composes: common; composes: primary from
“../shared/colors.css”; }

应用组件,大家可以像引用本地类名一样,引用colors.css文件的类。而且,组件变化的类名在出口时会被改动,但CSS文件本身并不转移,composes块也会在变更浏览器端CSS此前被剔除。

/* colors.css */
.shared_colors__primary__fca929 { color: #720; }
.shared_colors__secondary__acf292 { color: #777; }

/* submit-button.css */
.components_submit_button__common__abc5436 { /* font-sizes,
padding, border-radius */ }
.components_submit_button__normal__def6547 {}

 

<button class=”shared_colors__primary__fca929
components_submit_button__common__abc5436
components_submit_button__normal__def6547″> Submit
</button>

 

实际,在浏览器端,normal没有自己的体裁。这是好工作,你可以添加新的语义化的目的,但不用去添加CSS样式。大家还足以做得更加多一些,

在全站开发中追加类名和视觉的一致性,在浏览器端收缩体制代码的大小。

旁注:能够动用csso检测并移除空类。

CSS Modules 使用教程

第4步:单一职分模块

零件的无敌之处在于描述一个要素是什么,而不修饰它的体制。它以一种分化的点子来映射页面实体(元素)和体制实体(样式规则)。

看一个旧的CSS例子

.some_element { font-size: 1.5rem; color: rgba(0,0,0,0); padding:
0.5rem; box-shadow: 0 0 4px -2px; }

一个要素,一些样式,很粗略。即使那样,依然存在部分题材:color,font-size,box-shadow,padding,这个都在此间指定了,但无能为力在此外地点使用。

俺们用SASS重构一下。

$large-font-size: 1.5rem;
$dark-text: rgba(0,0,0,0);
$padding-normal: 0.5rem;
@mixin subtle-shadow { box-shadow: 0 0 4px -2px; }
.some_element {
@include subtle-shadow;
font-size: $large-font-size;
color: $dark-text;
padding: $padding-normal;
}

比旧的CSS样式有很大的改进,大家只是概念了很少的一部分。事实上像$large-font-size是排版,$padding-normal是布局,这几个都可是用名字表明含义,不会在任何地点运作。若是要声Bellamy(Bellamy)个box-shadow变量,但它并不可能表明自己含义,那时就无法不运用@mixin@extend了。

第4步:单一职务模块

零件的强大之处在于描述一个因素是怎么着,而不修饰它的样式。它以一种不一致的法子来映射页面实体(元素)和体裁实体(样式规则)。

看一个旧的CSS例子

.some_element { font-size: 1.5rem; color: rgba(0,0,0,0); padding:
0.5rem; box-shadow: 0 0 4px -2px; }

一个元素,一些体裁,很简单。就算这样,依然存在有的标题:color,font-size,box-shadow,padding,那个都在此处指定了,但不可以在其余地点选拔。

我们用SASS重构一下。

$large-font-size: 1.5rem;
$dark-text: rgba(0,0,0,0);
$padding-normal: 0.5rem;
@mixin subtle-shadow { box-shadow: 0 0 4px -2px; }
.some_element {
@include subtle-shadow;
font-size: $large-font-size;
color: $dark-text;
padding: $padding-normal;
}

比旧的CSS样式有很大的精雕细刻,大家只是概念了很少的一有些。事实上像$large-font-size是排版,$padding-normal是布局,这几个都仅仅用名字表明含义,不会在其余地点运作。假使要声美素佳儿个box-shadow变量,但它并无法宣布自我含义,那时就亟须选择@mixin@extend了。

启用 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

<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模块

透过选择组件,大家得以在组件中,注释写明哪些可以重复使用的类名。

.element {
composes: large from “./typography.css”;
composes: dark-text from “./colors.css”;
composes: padding-all-medium from “./layout.css”;
composes: subtle-shadow from “./effect.css”;
}

选取文件系统,而不是命名空间,来划分不相同用途的样式。自然会冒出引用多少个十足用途的文本。

如果你想从一个文书中援引七个类,那里有一个方便的方法:

/* this short hand: */
.element {
composes: padding-large margin-small from “./layout.css”;
}
/* is equivalent to: */
.element {
composes: padding-large from “./layout.css”;
composes: margin-small from “./layout.css”;
}

使您在网站开发上,每一种视觉对应一个类名。用地点的法门,来开发你的网站,变为一种可能。

.article {
composes: flex vertical centered from “./layout.css”;
}
.masthead {
composes: serif bold 48pt centered from “./typography.css”;
composes: paragraph-margin-below from “./layout.css”;
}
.body {
composes: max720 paragraph-margin-below from “layout.css”;
composes: sans light paragraph-line-height from “./typography.css”;
}

那是一种自己有趣味越来越探索的技能。在我看来,它整合了像Tachyons的原子CSS技术,像Semantic
UI体制类名的可读性,单一义务等优势。

但CSS模块的故事才刚刚开头,希望您能去在现今或将来采用它,并传播它。

使用CSS模块

透过动用组件,大家得以在组件中,注释写明哪些可以重复使用的类名。

.element {
composes: large from “./typography.css”;
composes: dark-text from “./colors.css”;
composes: padding-all-medium from “./layout.css”;
composes: subtle-shadow from “./effect.css”;
}

利用文件系统,而不是命名空间,来划分不相同用途的体制。自然会师世引用多个单纯用途的文书。

倘若你想从一个文件中引用七个类,这里有一个轻便的措施:

/* this short hand: */
.element {
composes: padding-large margin-small from “./layout.css”;
}
/* is equivalent to: */
.element {
composes: padding-large from “./layout.css”;
composes: margin-small from “./layout.css”;
}

使你在网站开发上,每一种视觉对应一个类名。用地点的法子,来支付你的网站,变为一种可能。

.article {
composes: flex vertical centered from “./layout.css”;
}
.masthead {
composes: serif bold 48pt centered from “./typography.css”;
composes: paragraph-margin-below from “./layout.css”;
}
.body {
composes: max720 paragraph-margin-below from “layout.css”;
composes: sans light paragraph-line-height from “./typography.css”;
}

那是一种自己有趣味越来越追究的技艺。在我看来,它结合了像Tachyons的原子CSS技术,像Semantic
UI体制类名的可读性,单一职分等优势。

但CSS模块的故事才刚刚起头,希望您能去在现行或以后拔取它,并传到它。

CSS Modules 在React中的实践

那么大家在React中怎么选取?

上手

因此选拔CSS模块,希望能支援你和您的团队,即可以调换当前的CSS知识和产品,又可以更舒服,更神速地做到工作。大家已经竭尽保持语法的简练,并写了一些事例,当你可以利用那一个事例里的代码时,你就足以运用它进行工作了。那里有一部分有关Webpack,JSPM和Browseriry品种的DEMO,希望对您所有帮衬。大家一直看有哪些新的环境可以运行CSS模块:正在适配服务器端NODEJS和Rails。

为了使业务更简便易行,那里做了一个Plunkr,可以直接入手,不用安装。早先吧

 亚洲必赢官网 9

假定您准备选拔了,可以看一看CSS模块源码,假若有如何难题,可以在issue里举办座谈。CSS模块组,规模小,不可以涵盖所有的使用场景。

希望你们的座谈。

祝:写样式喜形于色。

原文:CSS Modules

原文链接:

上手

透过利用CSS模块,希望能扶助您和您的团组织,即可以互换当前的CSS知识和制品,又可以更舒畅(英文名:Jennifer),更便捷地形成工作。我们早已竭尽保持语法的概括,并写了有的例证,当你可以使用那些事例里的代码时,你就足以应用它进行工作了。那里有部分有关Webpack,JSPM和Browseriry类其余DEMO,希望对你抱有协助。我们一向看有哪些新的环境足以运行CSS模块:正在适配服务器端NODEJS和Rails。

为了使工作更简单,那里做了一个Plunkr,能够一向出手,不用安装。先河吧

 亚洲必赢官网 10

倘使您准备选取了,可以看一看CSS模块源码,假若有怎样问题,可以在issue里进行座谈。CSS模块组,规模小,不可以涵盖所有的施用场景。

但愿你们的座谈。

祝:写样式神采飞扬。

原文:CSS Modules

原文链接:

手动引用解决

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
可以已毕选择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 收藏
评论

亚洲必赢官网 11

网站地图xml地图