前端的發展太快了,之前拜讀了一篇在 2016 年學 JavaScript 是一種什么樣的體驗?,不禁感慨,放一個三年前的前端來看待現在的前端圈子,估計也是懵逼的。
言歸正傳
我取標題的能力也是挺瞎的……
引言吐槽了一下javascript的蓬勃發展,其實并非是壞事,例如ES2015的發布和使用確實讓我感受到敲代碼時候很大的方便,比如箭頭函數(笑)。但相對而言的,CSS的發展卻并不是那么快。
可以想到的無非是各種預處理器
- LESS
- SASS
- 以及以后比較流行的postcss
但是他們還是沒有解決一個問題,命名的痛苦……
試想一下,一個大的項目,css命名滿天飛,一不留神就覆蓋了全局的class名怎么辦?
** css究竟怎么了?**
- 全局污染
- 命名混亂
- 依賴管理不徹底
怎么辦,試試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 *
項目結構
- 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)