菜单

CSS Modules 详解及 React 中执

2018年11月15日 - CSS/CSS3

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
模块化解决方案。近期于项目中大量用,下面具体享受下实行备受之底细和想法。

 

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;

总结

CSS Modules 很好的化解了 CSS 目前面临的模块化难题。支持及
Sass/Less/PostCSS
等搭配使用,能充分利用现有技术积淀。同时也克同全局样式灵活搭配,便于项目蒙日渐搬迁至
CSS Modules。CSS Modules
的贯彻啊属于轻量级,未来时有发生业内解决方案后方可低本钱迁移。如果你的产品受恰恰遇到类似问题,非常值得一试。

1 赞 2 收藏
评论

图片 2

何以咱们得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 链接: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’ }] }

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 中之样式且是一对的。

JS CSS无法共享变量

复杂组件要动 JS 和 CSS 来共同处理体制,就会见促成小变量在 JS 和 CSS
中冗余,CSS预处理器/后甩卖器 等还不提供跨 JS 和 CSS 共享变量这种力量。

CSS Modules 模块化方案

图片 3

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 实现了以下几点:

体默认局部

动了 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
单级别,分别是:

综上,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 入门及 React 中实践

2017/03/25 · CSS ·
React

原文出处:
AlloyTeam   

CSS Modules 使用技巧

CSS Modules 是针对性现有的 CSS
做减法。为了追求**简易但控**,作者建议按照如下原则:

面两漫漫标准相当给削弱了体制中不过灵的有的,初使用者很麻烦接受。第一久实施起来难度不慌,但第二长达如果模块状态了多时,class
数量将倍加上升。

得要明了,上面用称为建议,是盖 CSS Modules
并无强制你肯定要是如此做。听起来有点格格不入,由于大部分 CSS
项目在深厚的历史遗留问题,过多的限制就意味着多迁移成本和及表面合作的资本。初期使用被肯定要部分妥协。幸运的凡,CSS
Modules 这点做的十分好:

1. 一旦自己对一个要素运用多只 class 呢?

没问题,样式依旧生效。

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

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

3. 如自身于 style 文件被使了 id 选择器,伪类,标签选择器等也?

尚未问题,所有这些选择器将非给转移,原封不动的产出在编译后底 css
中。也就是说 CSS Modules 只会变换 class 名相关样式。

但注意,上面 3 个“如果”尽量不要产生

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
样式的导入和导出。灵活按需要导入以便复用代码;导出时如果力所能及隐藏其间作用域,以免造成全局污染。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。

 

CSS Modules 用教程

CSS模块化方案分类

CSS 模块化的缓解方案来许多,但主要发生三类。

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取前置到编译阶段。

运用JS 来治本体制模块

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

CSS Modules 能最大化地组成现有 CSS 生态(预处理器/后电脑等)和 JS
模块化能力,几乎零读书成本。只要您采取
Webpack,可以于其余类型受到使。是作者以为当下极端好之 CSS 模块化解决方案。

CSS in JS

穷废弃 CSS,用 JavaScript 写 CSS 规则,并内联样式。 React: CSS in JS
// Speaker
Deck。Radium,react-style
属于即同近似。但存在以下问题:
* 无法利用伪类,媒体询问等
* 样式代码也会起大量重。
* 不可知采用成熟之 CSS 预处理器(或后电脑)

最后

CSS Modules 很好的缓解了 CSS 目前面临的模块化难题。支持及
CSS处理器搭配使用,能充分利用现有技术积淀。如果您的出品受到正好撞类似问题,非常值得一试跳。

要大家都能够写有健康并且只是扩大的CSS,以上。

1 赞 2 收藏
评论

图片 4

手动引用解决

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>

形容以前方

读文先押这图,能先来只盖概念:

图片 5

阅读本文需要 11m 24s。

强健并且扩张方便的CSS

用作有追求的工程师,编写健壮并且扩张方便之CSS一直是我们的对象。那么哪些定义健壮并且扩张方便?有三单要点:

CSS 命名约定

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

做事原理

这就是说该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全局作用域问题

CSS的条条框框都是全局的,任何一个零件的样式规则,都对准全体页面中。相信写css的人口犹见面遇见样式冲突(污染)的题目。

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

于是亟待解决的题材不怕是css局部作用域避免全局样式冲突(污染)的题目

CSS Modules 以React中的施行

那么我们以React中怎么采取?

动用实例

当成熟之色受到,一般还见面为此到CSS预处理器或者后电脑。

此地因为用了stylusCSS预处理器为例子,我们来拘禁下哪些利用。

Shell

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

1
npm install -save-dev sugerss babel-plugin-react-css-modules
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

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 学习成本

相关文章

标签:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图