CSS Modules入门及React中实践(内附webpack4配置)
本篇文章以整理为主,自己进行了部分修改,如有侵权,请告知
CSS Modules介绍
CSS Modules是什么东西呢?首先,让我们从官方文档入手:
GitHub – css-modules/css-modules: Documentation about css-modules
CSS模块就是所有的类名都只有局部作用域的CSS文件。
所以CSS Modules既不是官方标准,也不是浏览器的特性,而是在构建步骤(例如使用Webpack或Browserify)中对CSS类名选择器限定作用域的一种方式(通过hash实现类似于命名空间的方法)。
在使用CSS模块时,类名是动态生成的,唯一的,并准确对应到源文件中的各个类的样式。
这也是实现样式作用域的原理。它们被限定在特定的模板里。例如我们在buttons.js里引入buttons.css文件,并使用.btn的样式,在其他组件里是不会被.btn影响的,除非它也引入了buttons.css.
可我们是出于什么目的把CSS和HTML文件搞得这么零碎呢?我们为什么要使用CSS模块呢?
为什么我们需要CSS模块化
CSS全局作用域问题,样式冲突(污染)的问题。
class命名写长一点吧,降低冲突的几率
加个父元素的选择器,限制范围
重新命名个class吧,比较保险
可是以上方案只是降低了全局冲突的概率,并不能彻底解决全局冲突的问题。并且,实现方式也不够优雅,还增加了代码的复杂和冗余。
JS CSS无法共享变量
我们的追求
面向组件 – 处理 UI 复杂性的最佳实践就是将 UI 分割成一个个的小组件 Locality_of_reference 。如果你正在使用一个合理的框架,JavaScript 方面就将原生支持(组件化)。举个例子,React 就鼓励高度组件化和分割。我们希望有一个 CSS 架构去匹配。
沙箱化(Sandboxed) – 如果一个组件的样式会对其他组件产生不必要以及意想不到的影响,那么将 UI 分割成组件并没有什么用。就这方面而言,CSS的全局作用域会给你造成负担。
方便 – 我们想要所有好的东西,并且不想产生更多的工作。也就是说,我们不想因为采用这个架构而让我们的开发者体验变得更糟。可能的话,我们想开发者体验变得更好。
CSS模块化方案分类
CSS 模块化的解决方案有很多,但主要有三类。
CSS 命名约定
规范化CSS的模块化解决方案(比如BEM BEM — Block Element Modifier,OOCSS,AMCSS,SMACSS,SUITCSS)
但存在以下问题:
* JS CSS之间依然没有打通变量和选择器等
* 复杂的命名
CSS in JS
彻底抛弃 CSS,用 JavaScript 写 CSS 规则,并内联样式。 React: CSS in JS // Speaker Deck。Radium,react-style 属于这一类。但存在以下问题:
* 无法使用伪类,媒体查询等
* 样式代码也会出现大量重复。
* 不能利用成熟的 CSS 预处理器(或后处理器)
关注点分离:是将计算机程序分成不同部分的设计原则,因此每个部分都需要解决一个独立的问题。HTML主要用于组织网页内容,CSS用于定义内容呈现风格,JS定义内容如何与用户交互和行为。
维基百科:https://en.wikipedia.org/wiki/Separation_of_concerns#HTML.2C_CSS.2C_JavaScript
使用JS 来管理样式模块
使用JS编译原生的CSS文件,使其具备模块化的能力,代表是 CSS Modules GitHub – css-modules/css-modules: Documentation about css-modules 。
CSS Modules 能最大化地结合现有 CSS 生态(预处理器/后处理器等)和 JS 模块化能力,几乎零学习成本。只要你使用 Webpack,可以在任何项目中使用。是笔者认为目前最好的 CSS 模块化解决方案。
CSS Modules 使用教程
webpack配置(版本为webpack4)
手动引用解决
在 className 处直接使用 css 中 class 名即可。
注意到 table--table-32osj 是 CSS Modules 按照 localIdentName 自动生成的 class 名。其中的 32osj 是按照给定算法生成的序列码。经过这样混淆处理后,class 名基本就是唯一的,大大降低了项目中样式覆盖的几率。同时在生产环境下修改规则,生成更短的 class 名,可以提高 CSS 的压缩率。
CSS Modules 实现了以下几点:
* 所有样式都是局部作用域的,解决了全局污染问题
* class 名生成规则配置灵活,可以此来压缩 class 名
* 只需引用组件的 JS 就能搞定组件所有的 JS 和 CSS
* 依然是 CSS,几乎 0 学习成本
babel-plugin-react-css-modules
babel-plugin-react-css-modules 可以实现使用styleName属性自动加载CSS模块。我们通过该babel插件来进行语法树解析并最终生成className。
以这种方式使用CSS模块有几个缺点:
您必须使用camelCase CSS类名称。
每当构造一个className时,你必须使用styles对象。
混合CSS模块和全局CSS类很麻烦。
对未定义的CSS模块的引用解决为未定义而没有警告。
您不必强迫使用camelCase命名约定。
每次使用CSS模块时,不需要引用样式对象。
全局CSS和CSS模块之间有明显的区别,例如
工作原理
那么该babel插件是怎么工作的呢?让我们从官方文档入手:
翻译如下:
1. 构建每个文件的所有样式表导入的索引(导入具有.css或.scss扩展名的文件)。
2. 使用postcss 解析匹配到的css文件
3. 遍历所有 JSX 元素声明
4. 把styleName 属性解析成匿名和命名的局部css模块引用
5. 查找与CSS模块引用相匹配的CSS类名称:
* 如果styleName的值是一个字符串字面值,生成一个字符串字面值。
* 如果是JSXExpressionContainer,在运行时使用helper函数来构建如果styleName的值是一个 jSXExpressionContainer, 使用辅助函数([getClassName]在运行时构造className值。
6. 从元素上移除styleName属性。
7. 将生成的className添加到现有的className值中(如果不存在则创建className属性)。
使用实例
在成熟的项目中,一般都会用到CSS预处理器或者后处理器。
这里以使用了scss预处理器为例子,我们来看下如何使用。
npm install -save-dev postcss-scss postcss-nested babel-plugin-react-css-modules
最后
CSS Modules 很好的解决了 CSS 目前面临的模块化难题。支持与 CSS处理器搭配使用,能充分利用现有技术积累。如果你的产品中正好遇到类似问题,非常值得一试。
CSS Modules入门及React中实践(内附webpack4配置)的更多相关文章
- 转 : CSS Modules详解及React中实践
https://zhuanlan.zhihu.com/p/20495964 CSS 是前端领域中进化最慢的一块.由于 ES2015/2016 的快速普及和 Babel/Webpack 等工具的迅猛发展 ...
- K8S生产环境中实践高可靠的配置和技巧都有哪些?
K8S环境中实践高可靠的配置和技巧都有哪些? 磁盘类型及大小 磁盘类型: 推荐使用ssd 磁盘 对于worker节点,创建集群时推荐使用挂载数据盘.这个盘是专门给/var/lib/docker 存放本 ...
- CSS modules 与 React中实践
最近一直在学习React,看上去蛮简单的内容,其实学习曲线还是比较高的. 目前学到css绑定的问题,看到有一篇好的文章,就转过来了. CSS 模块化的解决方案有很多,但主要有两类.一类是彻底抛弃 CS ...
- Immutable 详解及 React 中实践
本文转自:https://github.com/camsong/blog/issues/3 Shared mutable state is the root of all evil(共享的可变状态是万 ...
- CSS Modules入门教程
为什么引入CSS Modules 或者可以这么说,CSS Modules为我们解决了什么痛点.针对以往我写网页样式的经验,具体来说可以归纳为以下几点: 全局样式冲突 过程是这样的:你现在有两个模块,分 ...
- 图形化Cisco设备管理实践(附安装配置视频)
图形化Cisco设备管理实践 Ciscoworks 2000是Cisco公司推出的基于SNMP协议的网络管理系统,通过它网络管理人员可以方便快捷地完成设备的配置.管理.监控和故障分析等任务, Cisc ...
- [转] Immutable 详解及 React 中实践
https://zhuanlan.zhihu.com/p/20295971 作者:camsong链接:https://zhuanlan.zhihu.com/p/20295971来源:知乎著作权归作者所 ...
- python入门神书!|python编程从入门到实践|内附网盘链接带提取码|
点击此处进入网盘下载地址 提取码:o39n 全书共有20章,书中的简介如下: 本书旨在让你尽快学会 Python ,以便能够编写能正确运行的程序 —— 游戏.数据可视化和 Web 应用程序,同时掌握让 ...
- PMP测试实践- 内附PMBOK中字与备考资料
最近笔者考了PMP(Project Management Professional )项目管理专业人士认证考试,主要为了系统学习下项目管理的整个过程与方法,结合PMP的理论与工作实践去更好的完成项目工 ...
随机推荐
- Service学习
一.采用startService方式开启服务 1.写一个服务类 public class PhoneService extends Service { private static final Str ...
- 如何写出高性能DOM?
为什么要写高性能DOM? 一个网站,在页面上承载最多内容的就是DOM,而且无论是我们通过加载JS.加载图片,他们也是通过写HTML标签来实现的.而我们性能优化要做的无非就是几大块: 站点的网络消耗 D ...
- LightOJ 1161 - Extreme GCD 容斥
题意:给你n个数[4,10000],问在其中任意选四个其GCD值为1的情况有几种. 思路:GCD为1的情况很简单 即各个数没有相同的质因数,所以求所有出现过的质因数次数再容斥一下-- 很可惜是错的,因 ...
- 从零开始开发一款app,所想到的
我在知乎上看到这个问题http://www.zhihu.com/question/27645587.我在阅读了各位大牛的答案后,再加上自己的思考,就有了这篇文章的内容. 从零开始开发一款app ...
- Codeforces 321E Ciel and Gondolas
传送门:http://codeforces.com/problemset/problem/321/E [题解] 首先有一个$O(n^2k)$的dp. # include <stdio.h> ...
- java 连接MySQL的代码
1.java connect MySQL as conding. https://www.cnblogs.com/centor/p/6142775.html
- ASP.NET 简单鼠标右键效果contextmenutrip
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx. ...
- ”未能加载文件或程序集“Oracle.DataAccess”或它的某一个依赖项
引用:http://www.cnblogs.com/joey0210/archive/2012/09/29/2708420.html 上一篇文章说到了DLL引用问题,主要是说的程序中如果使用过了反射, ...
- CentOS7修改默认运行级别
新装了一个虚拟机,图形界面启动太慢,想调整一下按照以前的经验改运行级别,输入: vi /etc/inittab 然后发现跟之前不一样了,在inittab设置不再生效: # inittab is no ...
- MongoDB的安装配置、基本操作及Perl操作MongoDB
MongoDB的安装配置.基本操作及Perl操作MongoDB http://www.myhack58.com/Article/60/63/2014/42353.htm