热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

CSSModules详解

CSSModules可不是在说“css模块化”这个好像在某些地方见过的词,它其实是特指一种近期才出现的技术手段。什么技术手段呢?下面小编来和大家一起学习一下

.title {
 color: silver;
}

然后又在后边写了一条类似的(选手2):


.title {
 color: gold;
}

因为名字相同,选手2就会和选手1打起来(让你丫冒充我!)。结果是选手2获胜,class名为title的元素,最终的color值为gold。

css里就像这样,随时可能一言不和就发生战争,结果输掉的一方就会被胜利的一方所覆盖。“层叠”一词可以说形象地描述了这个过程。

那么,为什么会有这样的层叠(zhàn zhēng )呢?

css的作用域问题

在Javascript里,可以做到这样的搭配:


var title = "silver";

(function(){
 var title = "gold";
 console.log(title); // gold
}());

console.log(title); // silver

利用Javascript的函数作用域,两位同样名为title的选手可以友好相处。

但回到css里的样式规则,情况就完全不是这么回事了。

css不是程序语言,但如果说要给它加一个作用域的概念的话,那就是:只有全局作用域。

无论分拆为多少个css文件,无论用怎样的方式引入,所有的样式规则都位于同一作用域,只要选择符近似,就有发生覆盖的可能。

减少相互影响的策略

为减少相互影响,避免预料之外的样式覆盖,我们一直以来想过很多办法。

比如你接手一个别人留下来的旧项目,接下来要新增一个标题元素的时候,你会有意识地不去使用.title这样模糊的class名,因为它太容易重名了。最终,你用的名称可能是:


.module-sp-title {
 color: deepskyblue;
}

即使你决定要用.title这个名字,你也会加上包含选择符作为限定:


.module-1 .title { 
 font-size: 18px;
}
/* ... */
.module-2 .title {
 font-size: 14px;
}

其中.module-1和.module-2的名字应该是唯一的,这样的代码在组件化(模块化)的开发风格里很常见。

此外,一些有名的css理论,如SMACSS,会建议你为所有布局样式使用l-或layout-的前缀,以示区分。

类似的做法还有很多,但归结起来,都是在尝试提供一种合理的命名约定。而合理的命名约定,的确是组织css代码的有效策略。

现在,我们有了新的可用策略,CSS Modules就是其中之一。

技术流的模块化

CSS Modules是一种技术流的组织css代码的策略,它将为css提供默认的局部作用域。

CSS Modules是如何做到的呢?来看一个CSS Modules的简单例子吧。

有这样的一个html元素:


a title for CSS Modules

按照普通css的写法,我们可以这样为它添加样式:


.title {
 background-color: snow;
}

现在我们改用CSS Modules。首先,css保持不变。然后,修改html的写法。不再这样直接写html,而是改为在Javascript文件里动态添加,这样做(css文件名为main.css):


var styles = require("./main.css");

var el = document.getElementById("example_title");
el.outerHTML = '

a title for CSS Modules

';

咦,require了一个css文件?对的,所以要用到webpack。编译后,html和css会变成这样:

module: {
 loaders: [{
  test: /\.css$/,
  loader: 'style!css?modules'
 }]
}

才发现一直用着的css-loader原来有这功能?其实,CSS Modules确实是一个后来才并入css-loader的新功能。

自定义生成的class名

名字都这样了,还怎么调试?”

为css-loader增加localIdentName参数,是可以指定生成的名字。localIdentName的默认值是[hash:base64],一般开发环境建议用类似这样的配置:


{
 test: /\.css$/,
 loader: 'style!css?modules&localIdentName=[name]__[local]___[hash:base64:5]'
}

同样应用到前面的例子里,这时候就会变成这样的结果:

import styles from './ScopedSelectors.css';

import React, { Component } from 'react';

export default class ScopedSelectors extends Component {

 render() {
 return (
  

Scoped Selectors

); } };

如果不使用React,还是那句话,只要有办法把变量风格的class名注入到html中,就可以用CSS Modules。原始的字符串拼接的写法显然很糟糕,但我们可以借助各种模板引擎和编译工具做一些改进。下面请看一个用Jade的参考示例。

想象一下你有一个用普通css的页面,但你想在一小块区域使用CSS Modules。这一块区域在一个容器元素里:


后用jade来写html(关联的css文件为module_sp.css):


- styles = require("./module_sp.css");
h2(class=styles.title) a title for CSS Modules

接下来,仍然是在Javascript里添加这段jade生成的html:


var el = document.getElementById("module_sp_container");
var template = require("./main.jade");
el.innerHTML = template();

最后,记得在css-loader启用CSS Modules的同时,增加jade-loader:


{
 test: /\.jade$/,
 loader: 'jade'
}

编译运行,就可以得到想要的结果。除Jade以外,还有些其他CSS Modules的html应用方案,推荐参考github上的这篇issue。

目前CSS Modules还在发展中,而且也在考虑改进CSS Modules下的html写作体验。CSS Modules团队成员有提到一个叫CSS Modules Injector的未来规划项目,目的是让开发者不用Javascript也可以使用CSS Modules(这就很接近原生html + css的组合了)。

CSS Modules下的样式复用

“样式都是唯一的了,怎么复用?”

我们已经说了挺多普通css单个全局作用域的坏处。但对应的,这也有一个很大的好处,就是便于实现样式的复用。css理论OOCSS也是在追求这一点。

CSS Modules提供一个composes方法用于样式复用。例如,你有一个btn.css里有一条:


.btn{
 display: inline-block;
}

然后,你在另一个CSS Module的module_sp.css里可以这样引入它:


.btn-sp{
 composes: btn from "./btn.css";
 font-size: 16px;
}

那么,这个p.btn-sp的DOM元素将会是:

var styles = require("./main.css");
console.log("styles = ", styles);

结果类似这样:


{
 "btn-sp": "_2SCQ7Kuv31NIIiVU-Q2ubA _2r6eZFEKnJgc7GLy11yRmV",
 title: "_1m-KkPQynpIso3ofWhMVuK"
}

这可以帮助理解CSS Modules是怎样工作的。

预编译器

sass等预编译器也可以用CSS Modules,对应的loader可能是这样:


{
 test: /\.scss$/,
 loader: 'style!css?modules!resolve-url!sass?sourceMap'
}

注意不要因为是sass就习惯性地用嵌套写法,CSS Modules并不适合使用包含选择符。

建议的命名方式

CSS Modules会把.title转换为styles.title,由于后者是用在Javascript中,因此驼峰命名会更适合。

如果像我之前那样写.btn-sp,需要注意在Javascript中写为styles["btn-sp"]。

此外,你还可以为css-loader增加camelCase参数来实现自动转换:


{
 test: /\.css$/,
 loader: 'style!css?modules&camelCase',
}

这样即便你写.btn-sp,你也可以直接在Javascript里用styles.btnSp。

结语

无论是一直以来我们认真遵循的命名约定,还是这个新的CSS Modules,目的都是一样的:可维护的css代码。我觉得就CSS Modules基本还是在写css这一点来说,它还是很友好的。

虽然本文为了严谨,结果写了相当长的篇幅,但希望你读过之后,还能觉得CSS Modules是简单易懂的。因为这样,我就达成我的目的:扣题,了。

推荐教程:《PHP》


以上就是CSS Modules 详解的详细内容,更多请关注 第一PHP社区 其它相关文章!


推荐阅读
  • 配置PicGo与Gitee结合Typora打造高效写作环境
    本文详细介绍了如何通过PicGo和Gitee搭建个人图床,并结合Typora实现高效的文章撰写。包括创建图床项目、生成访问令牌、安装配置PicGo和Typora等步骤。 ... [详细]
  • HDU1085 捕获本·拉登!
    问题描述众所周知,本·拉登是一位臭名昭著的恐怖分子,他已失踪多年。但最近有报道称,他藏匿在中国杭州!虽然他躲在杭州的一个洞穴中不敢外出,但近年来他因无聊而沉迷于数学问题,并声称如果有人能解出他的题目,他就自首。 ... [详细]
  • 本文介绍了多种Eclipse插件,包括XML Schema Infoset Model (XSD)、Graphical Editing Framework (GEF)、Eclipse Modeling Framework (EMF)等,涵盖了从Web开发到图形界面编辑的多个方面。 ... [详细]
  • BeautifulSoup4 是一个功能强大的HTML和XML解析库,它能够帮助开发者轻松地从网页中提取信息。本文将介绍BeautifulSoup4的基本功能、安装方法、与其他解析工具的对比以及简单的使用示例。 ... [详细]
  • 本文介绍了如何使用Maven命令对Spring Boot项目中的子模块进行独立打包,包括依赖树的查看、项目的运行和打包等基本操作。 ... [详细]
  • 深入理解异步多线程编程模型
    现代计算机系统中的CPU通过并行处理提高效率,但所谓的并发处理实际上是一种基于轮询的模拟并行。本文探讨了现代处理器如何通过虚拟化技术实现更高的并发性能,以及在.NET框架中如何有效利用线程和异步编程模式。 ... [详细]
  • 本文通过具体示例详细介绍了 Python 中的装饰器和装饰类的使用方法,包括带参数的装饰器和装饰类的应用场景。 ... [详细]
  • 解决 Pytest 运行时出现 FileNotFoundError 的方法
    在使用 Pytest 进行测试时,可能会遇到 FileNotFoundError 错误,提示无法找到指定的文件或目录。本文将探讨该错误的原因及解决方案。 ... [详细]
  • SpringBoot新手入门指南
    本文旨在为初次接触SpringBoot的开发者提供一份详细的入门指导,包括如何快速搭建并运行一个简单的SpringBoot应用。通过本文,读者将了解Maven项目的构建、必要的配置文件设置以及基本的应用开发流程。 ... [详细]
  • 本视频详细介绍了如何利用J2EE、JBPM 3.x/4.3、Flex流程设计器、jQuery以及授权认证机制构建高效的企业普及版贝斯OA及工作流管理系统。 ... [详细]
  • BL550721、特点液晶驱动输出:Common输出4线,Segment输出36线内置显示寄存器364144bit2线串行接口(SCL,SDA)内置震荡电路内置液晶驱动电源电路13 ... [详细]
  • 本文介绍了如何在Windows操作系统中安装FFTW库,并详细说明了使用Visual Studio 2010进行4096点快速傅里叶变换(FFT)的步骤。包括下载预编译文件、生成库文件以及配置环境等关键环节。 ... [详细]
  • javascript——对象的概念——函数 1 (函数对象的属性和方法)
    一、创建函数函数是一种对象:Function类是对象,可以通过Function实例化一个函数,不过最多的还是利用function来创建函数。方式一:利用Function类来实例化函 ... [详细]
  • IEC60825激光产品安全标准详解
    随着激光技术在全球范围内的广泛应用,尤其是激光投影显示技术的兴起,了解和遵守相关的安全标准变得尤为重要。本文将详细介绍IEC60825激光产品安全标准及其重要性。 ... [详细]
  • Mysqlcheck作为MySQL提供的一个实用工具,主要用于数据库表的维护工作,包括检查、分析、修复及优化等操作。本文将详细介绍如何使用Mysqlcheck工具,并提供一些实践建议。 ... [详细]
author-avatar
绿色好心情
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有