我爱编程

初识CSS Modules

2016-11-15  本文已影响0人  snoopy1412

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

言归正传

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


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

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

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

** css究竟怎么了?**

  1. 全局污染
  2. 命名混乱
  3. 依赖管理不彻底
怎么办,试试BEM呗

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

举个例子

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

啥都别说了……

CSS modules来了

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

CSS modules语法篇

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

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(命名规则其实是可以自行调整的,下面会提到)

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;}
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

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'**实现了两个文件之间的组合。

5. 输入变量

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

CSS modules 使用实例

*这里使用 webpack *

项目结构

假设项目的文件夹是 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)
上一篇下一篇

猜你喜欢

热点阅读