将来的编码格局

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发布于二零一五年5月19日的一篇作品,首若是事先翻译的作品《掌握CSS模块方法》里提到那篇小说,现在到底顺藤摸瓜跟进来看看。

这边的翻译都是基于自家要好的精通举行的,所以不是一句一句的来的,有哪些不对的也在所难免,水平有限,希望大家提出。

CSS 模块化碰着了哪些难点?

CSS 模块化首要的是要解决好三个难点:CSS
样式的导入和导出。灵活按需导入以便复用代码;导出时要可以隐藏其中效能域,以防导致全局污染。Sass/Less/PostCSS
等后续试图缓解 CSS
编程能力弱的标题,结果它们做的也着实不错,但那并从未缓解模块化最要害的题材。Facebook工程师 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开发合计上找到一个扭转点,最好去找Christopher Chedeau
二零一四年3月在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开发考虑上找到一个变型点,最好去找Christopher Chedeau
二〇一四年10月在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是布局,那几个都仅仅用名字表达含义,不会在任啥地方方运作。假诺要声雀巢(Nestle)(Nutrilon)个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是布局,那个都仅仅用名字表明含义,不会在其余地点运作。假使要声惠氏(WYETH)个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知识和制品,又有什么不可更舒适,更快捷地做到工作。我们已经竭尽保持语法的简便,并写了部分例证,当您可以利用那么些事例里的代码时,你就足以选取它进行工作了。那里有一对关于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地图