初识CSS Modules

作者: snoopy1412 | 来源:发表于2016-11-15 21:10 被阅读0次

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

    言归正传

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


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

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

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

    试想一下,一个大的项目,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 *

    项目结构

    • 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)

    相关文章

      网友评论

        本文标题:初识CSS Modules

        本文链接:https://www.haomeiwen.com/subject/ttclpttx.html