CSS模块介绍
时间:2023-03-30 14:51:14
CSS
前端开发越来越快,这应该是每个前端开发者的亲身体验,但CSS却是前端领域中发展最慢的部分。ES678的迅速普及,使得前端工程越来越成熟,CSS已经被远远甩在了后面。JS语言模块已经标准化,CSS还在探索中。同时,这也是一个亟待解决的问题。如果您以前从未听说过CSS模块,那么本文适合您。如果您知道它,则无需再阅读它,因为它真的很简单(而且功能强大)。我们都知道CSS的痛点。CSS入门容易,深入难。简单的样式很难维护。CSS痛点也很多。1、CSS规则是全局的,任何一个组件的样式规则对整个页面都有效。相信写css的人都会遇到样式冲突(污染)的问题。2.为了解决全局污染的问题,让我们把类名写的长一点,加一个父选择器,减少冲突的几率,这样CSS命名就乱了。3、组件依赖管理不彻底,组件之间应该相互独立。导入组件时,只导入组件需要的CSS样式。4.代码难以复用。sassless、CSS模块化方案等工具应运而生。前端发展很快,每天都有新的轮子。自然而然,CSS模块化的解决方案有很多,但主要分为三大类:1、命名规范和标准化的CSS解决方案如:BEM、OOCSS、AMCSS、SMACSS2、CSSinJS完全摒弃CSS,使用JavaScript编写CSS规则,styled-components就是代表之一。3、使用JS管理样式模块使用JS编译原生CSS文件,使其模块化,以CSSModules为代表。但是这些模块化的方案各有优缺点,比如命名规范:命名复杂,CSSinJS:缺乏扩展,CSSModules,当然也有一些缺点(先学习一下再说优缺点).在众多的解决方案中,没有绝对的优势或劣势。还是要根据自己的场景来决定。使用CSSModulesCSSModules并没有将CSS转化为编程能力,而是增加了局部作用域和依赖管理,刚好解决了最大的痛点。可以有效避免全局污染和样式冲突,可以最大限度的结合现有的CSS生态和JS模块化能力。启用CSS模块CSS模块很容易学习。webpack自带的css-loader组件自带CSSModules,通过简单配置即可使用。//webpack.config.jsconstpath=require('path')module.exports={entry:__dirname+'/src/index.js',output:{filename:'bundle.js',path:path.resolve(__dirname,'dist')},module:{rules:[{test:/\.css$/,use:['style-loader',{loader:'css-loader',options:{modules:true,}}]}]}}//你也可以使用下面的语法//loader:"style-loader!css-loader?modules"现在让我们写一个Button组件/*Button.css*/.primary{background-color:#1aad19;颜色:#fff;边框:无;border-radius:5px;}//Button.jsimportstylesfrom'./Button.css';console.log(styles);//->{primary:"yTXmm0isaXExoYiZUvKxH"}constButton=document.createElement('div')Button.innerHTML=`提交`导出默认按钮//索引.jsimportButtonfrom'./components/Button'constapp=document.getElementById('root')app.appendChild(Button)将HTML生成为Submit
CSSModules处理CSS中所有的类名,用对象保存原类和混淆类的对应关系。CSSModules自动生成的类名基本是唯一的,大大降低了项目的成本。样式覆盖冲突的机会。GitHub示例库https://github.com/liuxing/css-modules-demo通过commit记录查看自定义类类名css-loader。默认的哈希算法是[hash:base64]。从前面我们可以发现,.primary被编译成了类似yTXmm0isaXExoYiZUvKxH这样的字符串。不用担心,css-loader为我们提供了localIdentName参数来指定生成名称的格式。localIdentName的默认值为[hash:base64]。...{loader:'css-loader',options:{modules:true,localIdentName:'[name]__[local]--[hash:base64:5]'}}//orloader:'style-loader!css-loader?modules&localIdentName=[name]__[local]--[hash:base64:5]'...不再需要BEM代码规范,熟悉BEM的同学可能会发现上面的命名有点类似BEM,虽然这个名字有点花哨,但BEM被非常多的大型项目和团队采用,是一种很好的实践。当然你可以根据自己的场景决定怎么写,不再需要遵守CSS模块中的BEM规范。范围通过前面的示例,您可以了解CSS模块处理CSS的方式。现在让我们从头开始讨论范围。默认局部作用CSS很多问题都是全局作用域引起的,如何生成局部作用域?通过前面的CSS模块例子,我们发现它的思路很简单,就是生成一个唯一的类名。CSS模块将类转换为对应的全局唯一哈希值,形成局部作用域。使用CSSModules后,相当于在每个类名中都加了一个:local。这是默认值,也可以显式使用。当然,如果你想切换到全局模式,CSSModules允许使用:global(.className)语法,来声明一个全局规则。以这种方式声明的任何类都不会被编译成哈希字符串。/*Button.css*/:global(.btn){颜色:#fff;边框:无;border-radius:5px;}.primary{background-color:#1aad19;}/*不要在上面添加`:local`等价的显式本地范围语法*/:local(.warn){background-color:#e64340}查看GitHub示例库的提交记录https://github.com/liuxing/css-modules-demoCSSModules下的样式重用对于样式重用,CSSModules提供了composes来处理。一个选择器可以继承另一个选择器的规则/*Button.css*/.btn{/*所有常用样式*/color:#fff;边框:无;边界半径:5px;box-sizing:border-box;}.??primary{composes:btn;background-color:#1aad19;}Button.jsimportstylesfrom'./Button.css';console.log(styles);constButton=document.createElement('div')Button.innerHTML=`
Submit`exportdefaultButton生成的html变成Submit
我们发现.btn是组合在.primary中的,.primary编译后会变成两个类。composes也可以继承组合其他CSS文件中的规则/*author.css*/.shadow{box-shadow:0020pxrgba(0,0,0,.2)}Button.css···.primary{组成:btn;组成:来自'./author.css'的影子;background-color:#1aad19;}···这是一个非常强大和方便的功能,CSSModules团队成员认为composes是CSSModules中最强大的功能:对我来说,CSSModules中最强大的想法是组合,你在哪里可以将您的视觉清单解构为原子类,并在模块级别组装它们,而不会重复标记或影响性能。一些建议简单可控,作者建议遵循以下原则:不使用选择器,只用类名定义样式不要级联多个类,只用一个类定义所有样式所有样式通过composes组合无需嵌套即可实现重用但建议只是建议,CSSModules不会强制你这样做。如何舒服如何来CSSModules解决了CSS目前面临的一些痛点和模块化问题,同时也支持Sass/Less/PostCSS的使用。无论是遵循规范的命名约定,还是使用本文介绍的CSSModules,其目的都是一样的:可维护的CSS代码。具体要不要用,要看你自己的场景。适合自己的才是最好的。可以关注我的公众号,一起玩。有技术干货和废话,关注回复【888】领取福利,左手代码,右手搬砖,抛砖引玉