金沙棋牌官方平台

当前位置:金沙棋牌 > 金沙棋牌官方平台 > 用法教程

用法教程

来源:http://www.logblo.com 作者:金沙棋牌 时间:2019-11-09 19:48

CSS Modules 用法教程

2016/06/19 · CSS · Modules

原文出处: 阮一峰   

学过网页开发就会知道,CSS 不能算编程语言,只是网页样式的一种描述方法。

为了让 CSS 也能适用软件工程方法,程序员想了各种办法,让它变得像一门编程语言。从最早的Less、SASS,到后来的 PostCSS,再到最近的 CSS in JS,都是为了解决这个问题。

图片 1

本文介绍的 CSS Modules 有所不同。它不是将 CSS 改造成编程语言,而是功能很单纯,只加入了局部作用域和模块依赖,这恰恰是网页组件最急需的功能。

因此,CSS Modules 很容易学,因为它的规则少,同时又非常有用,可以保证某个组件的样式,不会影响到其他组件。

图片 2

webpack 之 css module

前端的发展太快了,之前拜读了一篇在 2016 年学 JavaScript 是一种什么样的体验?,不禁感慨,放一个三年前的前端来看待现在的前端圈子,估计也是懵逼的。

CSS Modules 入门及 React 中实践

2017/03/25 · CSS · React

原文出处: AlloyTeam   

零、示例库

我为这个教程写了一个示例库,包含六个Demo。通过它们,你可以轻松学会CSS Modules。

首先,克隆示例库。

JavaScript

$ git clone

1
$ git clone https://github.com/ruanyf/css-modules-demos.git

然后,安装依赖。

JavaScript

$ cd css-modules-demos $ npm install

1
2
$ cd css-modules-demos
$ npm install

接着,就可以运行第一个示例了。

JavaScript

$ npm run demo01

1
$ npm run demo01

打开浏览器,访问

webpack配置
css-loader?modules
modules 字段表示开启css module

言归正传

我取标题的能力也是挺瞎的……


引言吐槽了一下javascript的蓬勃发展,其实并非是坏事,例如ES2015的发布和使用确实让我感受到敲代码时候很大的方便,比如箭头函数(笑)。但相对而言的,CSS的发展却并不是那么快。
可以想到的无非是各种预处理器

  • LESS
  • SASS
  • 以及以后比较流行的postcss

但是他们还是没有解决一个问题,命名的痛苦……

试想一下,一个大的项目,css命名满天飞,一不留神就覆盖了全局的class名怎么办?

** css究竟怎么了?**

  1. 全局污染
  2. 命名混乱
  3. 依赖管理不彻底

写在前面

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

图片 3

阅读本文需要 11m 24s。

一、局部作用域

CSS的规则都是全局的,任何一个组件的样式规则,都对整个页面有效。

产生局部作用域的唯一方法,就是使用一个独一无二的class的名字,不会与其他选择器重名。这就是 CSS Modules 的做法。

下面是一个React组件App.js。

JavaScript

import React from 'react'; import style from './App.css'; export default () => { return ( <h1 className={style.title}> Hello World </h1> ); };

1
2
3
4
5
6
7
8
9
10
import React from 'react';
import style from './App.css';
 
export default () => {
  return (
    <h1 className={style.title}>
      Hello World
    </h1>
  );
};

上面代码中,我们将样式文件App.css输入到style对象,然后引用style.title代表一个class。

CSS

.title { color: red; }

1
2
3
.title {
  color: red;
}

构建工具会将类名style.title编译成一个哈希字符串。

XHTML

<h1 class="_3zyde4l1yATCOkgn-DBWEL"> Hello World </h1>

1
2
3
<h1 class="_3zyde4l1yATCOkgn-DBWEL">
  Hello World
</h1>

App.css也会同时被编译。

JavaScript

._3zyde4l1yATCOkgn-DBWEL { color: red; }

1
2
3
._3zyde4l1yATCOkgn-DBWEL {
  color: red;
}

这样一来,这个类名就变成独一无二了,只对App组件有效。

CSS Modules 提供各种插件,支持不同的构建工具。本文使用的是 Webpack 的css-loader插件,因为它对 CSS Modules 的支持最好,而且很容易使用。顺便说一下,如果你想学 Webpack,可以阅读我的教程Webpack-Demos。

下面是这个示例的webpack.config.js。

JavaScript

module.exports = { entry: __dirname + '/index.js', output: { publicPath: '/', filename: './bundle.js' }, module: { loaders: [ { test: /.jsx?$/, exclude: /node_modules/, loader: 'babel', query: { presets: ['es2015', 'stage-0', 'react'] } }, { test: /.css$/, loader: "style-loader!css-loader?modules" }, ] } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module.exports = {
  entry: __dirname + '/index.js',
  output: {
    publicPath: '/',
    filename: './bundle.js'
  },
  module: {
    loaders: [
      {
        test: /.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          presets: ['es2015', 'stage-0', 'react']
        }
      },
      {
        test: /.css$/,
        loader: "style-loader!css-loader?modules"
      },
    ]
  }
};

上面代码中,关键的一行是style-loader!css-loader?modules,它在css-loader后面加了一个查询参数modules,表示打开 CSS Modules 功能。

现在,运行这个Demo。

JavaScript

$ npm run demo01

1
$ npm run demo01

打开 ,可以看到结果,h1标题显示为红色。

定制css类名规则
modules&localIdentName=[path][name]---[local]---[hash:base64:5]
localIdentName 字段定义css类名规则

怎么办,试试BEM呗

你还真别说,业界确实有一个非常不错的css命名规范,BEM(不展开了),有兴趣的自行搜索一下吧,BEM规范的好处在于尽可能的解决了css命名全局污染的问题。但是,它的规则真的太麻烦了,还不好记。

举个例子

.block{} /* 块 */
.block__element{} /* 元素 */
.block--modifier{} /* 修饰符 */

啥都别说了……

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 Modules 允许使用:global(.className)的语法,声明一个全局规则。凡是这样声明的class,都不会被编译成哈希字符串。

App.css加入一个全局class。

JavaScript

.title { color: red; } :global(.title) { color: green; }

1
2
3
4
5
6
7
.title {
  color: red;
}
 
:global(.title) {
  color: green;
}

App.js使用普通的class的写法,就会引用全局class。

JavaScript

import React from 'react'; import styles from './App.css'; export default () => { return ( <h1 className="title"> Hello World </h1> ); };

1
2
3
4
5
6
7
8
9
10
import React from 'react';
import styles from './App.css';
 
export default () => {
  return (
    <h1 className="title">
      Hello World
    </h1>
  );
};

运行这个示例。

JavaScript

$ npm run demo02

1
$ npm run demo02

打开

CSS Modules 还提供一种显式的局部作用域语法:local(.className),等同于.className,所以上面的App.css也可以写成下面这样。

JavaScript

:local(.title) { color: red; } :global(.title) { color: green; }

1
2
3
4
5
6
7
:local(.title) {
  color: red;
}
 
:global(.title) {
  color: green;
}

引入:
import style from './App.css';
style.title{}

CSS modules来了

要说js模块化,这几年真是讲烂了,什么AMD,CMD,UMD各种,以及ES2015原生都开始支持js模块化。讲真,在我开始接触了模块化js之后确实给我带来了很多的方便(点个赞)。
同样,CSS module的带来或许也可能解决目前大家最头疼的CSS 全局污染问题了。

为什么我们需要CSS模块化

三、定制哈希类名

css-loader默认的哈希算法是[hash:base64],这会将.title编译成._3zyde4l1yATCOkgn-DBWEL这样的字符串。

webpack.config.js里面可以定制哈希字符串的格式。

JavaScript

module: { loaders: [ // ... { test: /.css$/, loader: "style-loader!css-loader?modules&localIdentName=[path][name]---[local]---[hash:base64:5]" }, ] }

1
2
3
4
5
6
7
8
9
module: {
  loaders: [
    // ...
    {
      test: /.css$/,
      loader: "style-loader!css-loader?modules&amp;localIdentName=[path][name]---[local]---[hash:base64:5]"
    },
  ]
}

运行这个示例。

JavaScript

$ npm run demo03

1
$ npm run demo03

你会发现.title被编译成了demo03-components-App—title—GpMto。

全局:
:global()
eg:
:global(.title){}

CSS modules语法篇

一切开始前,要表示一下,CSS modules不是一个新语言,而只是CSS in JS一直实现方式,最值得重视的是,它的规则特别少,几乎0成本!这部分参考了阮一峰大神的CSS Modules 用法教程

CSS全局作用域问题

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

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

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

四、 Class 的组合

在 CSS Modules 中,一个选择器可以继承另一个选择器的规则,这称为”组合”(“composition”)。

在App.css中,让.title继承.className 。

JavaScript

.className { background-color: blue; } .title { composes: className; color: red; }

1
2
3
4
5
6
7
8
.className {
  background-color: blue;
}
 
.title {
  composes: className;
  color: red;
}

App.js不用修改。

JavaScript

import React from 'react'; import style from './App.css'; export default () => { return ( <h1 className={style.title}> Hello World </h1> ); };

1
2
3
4
5
6
7
8
9
10
import React from 'react';
import style from './App.css';
 
export default () => {
  return (
    <h1 className={style.title}>
      Hello World
    </h1>
  );
};

运行这个示例。

JavaScript

$ npm run demo04

1
$ npm run demo04

打开

App.css编译成下面的代码。

JavaScript

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

1
2
3
4
5
6
7
._2DHwuiHWMnKTOYG45T0x34 {
  color: red;
}
 
._10B-buq6_BEOTOl9urIjf8 {
  background-color: blue;
}

相应地, h1的class也会编译成<h1 class=”_2DHwuiHWMnKTOYG45T0x34 _10B-buq6_BEOTOl9urIjf8″>。

class组合:
composes:classname;

1. 局部作用域

说白了,使用CSS modules ,每一个class都可以生成一个唯一的class名

例如
创建一个button.css文件,并写入代码

.red{
   color:red  
}

引入到另一个index.js(省略了一部分代码)

import buttons from "./buttons.css";
element.innerHTML = `<div class="${buttons.red}">`

那么,在渲染到html文件里面的时候,这里的class可能就是_3N_PGYCwi_3X8rf_WN50yo(命名规则其实是可以自行调整的,下面会提到)

JS CSS无法共享变量

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

五、输入其他模块

选择器也可以继承其他CSS文件里面的规则。

another.css

JavaScript

.className { background-color: blue; }

1
2
3
.className {
  background-color: blue;
}

App.css可以继承another.css里面的规则。

JavaScript

.title { composes: className from './another.css'; color: red; }

1
2
3
4
.title {
  composes: className from './another.css';
  color: red;
}

运行这个示例。

JavaScript

$ npm run demo05

1
$ npm run demo05

打开

引入其他模块:
composes: classname from ’./style.css’;

2. 全局作用域

CSS Modules 允许使用:global(.className)的语法,声明一个全局规则。凡是这样声明的class,都不会被编译成哈希字符串。

.title { color: red;}
:global(.title) { color: green;}

第二个渲染的class依然是.title

CSS Modules 还提供一种显式的局部作用域语法:local(.className),等同于.class,所以上述的css文件也可以写成下面这样。

:local(.title) { color: red;}
:global(.title) { color: green;}

健壮并且扩展方便的CSS

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

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

六、输入变量

CSS Modules 支持使用变量,不过需要安装 PostCSS 和 postcss-modules-values。

JavaScript

$ npm install --save postcss-loader postcss-modules-values

1
$ npm install --save postcss-loader postcss-modules-values

把postcss-loader加入webpack.config.js。

JavaScript

var values = require('postcss-modules-values'); module.exports = { entry: __dirname + '/index.js', output: { publicPath: '/', filename: './bundle.js' }, module: { loaders: [ { test: /.jsx?$/, exclude: /node_modules/, loader: 'babel', query: { presets: ['es2015', 'stage-0', 'react'] } }, { test: /.css$/, loader: "style-loader!css-loader?modules!postcss-loader" }, ] }, postcss: [ values ] };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var values = require('postcss-modules-values');
 
module.exports = {
  entry: __dirname + '/index.js',
  output: {
    publicPath: '/',
    filename: './bundle.js'
  },
  module: {
    loaders: [
      {
        test: /.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          presets: ['es2015', 'stage-0', 'react']
        }
      },
      {
        test: /.css$/,
        loader: "style-loader!css-loader?modules!postcss-loader"
      },
    ]
  },
  postcss: [
    values
  ]
};

接着,在colors.css里面定义变量。

JavaScript

@value blue: #0c77f8; @value red: #ff0000; @value green: #aaf200;

1
2
3
@value blue: #0c77f8;
@value red: #ff0000;
@value green: #aaf200;

App.css可以引用这些变量。

JavaScript

@value colors: "./colors.css"; @value blue, red, green from colors; .title { color: red; background-color: blue; }

1
2
3
4
5
6
7
@value colors: "./colors.css";
@value blue, red, green from colors;
 
.title {
  color: red;
  background-color: blue;
}

运行这个示例。

JavaScript

$ npm run demo06

1
$ npm run demo06

打开

1 赞 3 收藏 评论

图片 4

引入变量:(postcss-loader ;postcss-modules-values)

3. 定制哈希类名

配合webpack食用更佳
举个配合webpack使用的例子

//webpack.config.js文件
……
module: { 
loaders: [  // ... 
{ 
 test: /.css$/, 
 loader: "style-loader!css-loader?modules&localIdentName=[path][name]---[local]---[hash:base64:5]" },
]
}

依然是上面的例子
创建一个button.css文件,并写入代码

.red{
   color:red  
}

那么,渲染的class可能是 .buttons__red___3N_PG

CSS模块化方案分类

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

  1. web pack配置增加 postcss: [require('postcss-modules-values') ]
  2. 语法(注意‘: ’ 号后空格,去掉会报错!)
    @value green: #aaf200; 定义变量
    @value colors: "./colors.css";
    @value blue, red, green from colors;
4. Class 的组合

在 CSS Modules 中,一个选择器可以继承另一个选择器的规则,这称为"组合"("composition")。

直接上代码
创建一个button.css文件,并写入代码

.red{
   color:red  
}
.button{
  composes:red
}

使用composes继承了class名为red的属性,有点类似于sass里面的@extend。

此外还支持两个模块的引入
例如
创建一个button.css文件,并写入代码

.red{
   color:red  
}

同目录创建一个button2.css文件,并写入代码

.button{
  composes:red from './button.css'
}

通过** composes:red from './button.css'**实现了两个文件之间的组合。

CSS 命名约定

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

5. 输入变量

接触不多,具体实现详见原文。

CSS in JS

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

CSS modules 使用实例

*这里使用 webpack *

项目结构

  • src (文件夹)
  • node_modules (文件夹)
  • .babelrc
  • index.html
  • webpack.config.js
  • package.json

假设项目的文件夹是 app, 在app文件夹内npm init 生成 package.json 文件
然后(请确认已全局安装webpack), npm install -D babel-core babel-loader babel-preset-es2015 extract-text-webpack-plugin css-loader webpack

在webpack.config.js中写入以下内容

var path = require('path')
var ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
    entry: './src',
    output: {
        path: 'bulid',
        filename: 'bundle.js'
    },
    module: {
        loaders: [{
            test: /.js$/,
            loader: 'babel-loader',
            include: path.resolve(__dirname, './src')
        }, {
            test: /.css$/,
            loader: ExtractTextPlugin.extract('css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'),
            include: path.resolve(__dirname, 'src'),
        }]
    },
    plugins: [
        new ExtractTextPlugin("styles.css")
    ],
    devtool: "source-map"
}

在.babelrc文件中写入

{
 "presets": ["es2015"]
}```

在index.html中写入

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document name</title>
<link rel="stylesheet" href="bulid/styles.css">
</head>
<body>
<h1>CSS Modules demo</h1>

<script src="bulid/bundle.js"></script>

</body>
</html>

准备工作做完,我们在src文件夹中进行具体的内容操作

###### step1 
在src中新建 index.js,内容

import buttons from './buttons.css'

let element = <div class="${buttons.red}"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur laudantium recusandae itaque libero velit minus ex reiciendis veniam. Eligendi modi sint delectus beatae nemo provident ratione maiores, voluptatibus a tempore!</p> </div>;
document.write(element);

###### setp2 
在src文件夹中新建buttons.css,内容

.red{
color:red
}

###### setp3 
在命令行中执行webpack任务,生成bulid文件夹。

命令行 输入   ```webpack``` 尝试一下吧!!
***
在上述的项目中,css modules的核心是webpack.config.js中 

{
test: /.css$/,
loader: ExtractTextPlugin.extract('css?modules&importLoaders=1&localIdentName=[name][local]_[hash:base64:5]'),
include: path.resolve(__dirname, 'src'),
}

# 文章参考
[CSS Modules入门Ⅰ:它是什么?为什么要使用它?
](https://zhuanlan.zhihu.com/p/23571898)
[CSS Modules入门Ⅱ:快速上手](https://zhuanlan.zhihu.com/p/23602046)
[CSS Modules 用法教程](http://www.bshare.cn/share)

使用JS 来管理样式模块

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

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

CSS Modules 使用教程

启用 CSS Modules

JavaScript

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

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

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

CSS

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

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

JavaScript

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

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

生成的 HTML 是

XHTML

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

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

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

上例中 console 打印的结果是:

CSS

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

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

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

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

CSS Modules 在React中的实践

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

手动引用解决

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

JavaScript

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

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

渲染出来的组件出来

XHTML

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

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

react-css-modules

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

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

JavaScript

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

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

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

babel-plugin-react-css-modules

babel-plugin-react-css-modules 可以实现使用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 收藏 评论

图片 5

本文由金沙棋牌发布于金沙棋牌官方平台,转载请注明出处:用法教程

关键词:

上一篇:ThinkPHP实例教程,技术栈开发web应用

下一篇:没有了