文章同步在GithubPines-Cheng/blog随着近几年前端的发展,CSS作为前端三剑客之一,各种技术方案层出不穷。从CSSprepocessor(SASS、LESS、Stylus)到后来的后起之秀PostCSS,再到CSSModules、Styled-Component等,有人维护了一份比较完整的CSSinJS技术方案,目前已有近50个技术方案。CSS模块就是其中之一。CSSModules简介要了解什么是CSSModules,可以先看官方介绍:GitHub-css-modules/css-modules:Documentationaboutcss-modules。从上面的介绍可以看出,CSSModules既不是官方标准也不是浏览器的特性,而是一种在构建步骤中限制CSS类名选择器范围的方式(比如使用Webpack或者Browserify)(通过hash实现一个命名空间类似的方法)。比如我们在buttons.js中导入buttons.css文件,使用.btn样式,就不会受到其他组件中.btn的影响,除非它也引入了buttons.css。CSS模块化JS已经完全实现模块化,但是css还处于探索阶段。为什么我们需要CSS模块化?主要是由于以下原因。CSS全局作用域问题CSS规则是全局的,任何组件的样式规则对整个页面都有效。现在的前端项目大多是基于组件开发的。随着项目页面数量和复杂度的增加,相信写CSS的都会遇到样式冲突(污染)的问题。一般我们会采用以下方法:将类名写长一些,减少冲突的概率,为父元素添加一个选择器,在限定范围内重命名类。比较安全,但是上面的方案只是降低了全局冲突的概率,并不能彻底解决全局冲突的问题。而且实现方式不够优雅,也增加了代码的复杂度和冗余度。我们对面向组件开发的追求:处理UI复杂性的最佳实践是将UI分成小的组件,而React鼓励高度的组件化和分割。我们希望有一个CSS模式来匹配。沙盒化:如果一个组件的样式可能对其他组件产生不需要的和意想不到的影响,那么将UI拆分为多个组件几乎没有用处。在这方面,CSS的全局范围会给你带来负担。方便:不会增加开发负担和代码冗余。解决方案CSS模块化的解决方案有很多,但主要分为三类。CSS命名约定规范了CSS模块化解决方案(如BEMBEM—BlockElementModifier、OOCSS、AMCSS、SMACSS、SUITCSS),但存在以下问题:JSCSS与变量、选择器CSS等复杂命名仍然没有联系在JS中完全抛弃CSS,用JavaScript编写CSS规则,以及内联样式。styled-components就是其中之一。styled-components让CSS真正意义上的写入JS,同时让标签更加语义化,这和HTML5新标签的思路是一样的;这个框架让style也有了组件化的思维,让前端完全面向组件化编程,就像java的Awrappertype。但是存在以下问题:样式代码也有很多重复。不能使用成熟的CSS预处理器(或后处理器)来使用JS来管理样式模块。使用JS编译原生CSS文件,使其模块化,以CSSModules为代表。CSSModule仍然是一种分离JS和CSS的方式,不会改变你的书写习惯。CSSModule只需修改构造代码,使用模块依赖引入className即可使用,支持less和sass语法。使用CSSModules可以使组件className的控制权转移给JS。我们不会关心命名冲突污染等问题。同时,我们可以灵活控制生成的命名。样式代码无需修改,老项目使用CSS语法即可零成本接入。CSSModules可以最大限度地结合现有的CSS生态(preprocessor/postprocessor等)和JS模块化能力,学习成本几乎为零。只要你使用Webpack,就可以在任何项目中使用。最好的CSS模块化解决方案。使用CSSModules配置非常简单。如果使用webpack,只需要在配置文件中改一行即可。//webpack.config.jscss?modules&localIdentName=[name]__[local]-[hash:base64:5]plusmodules启用,localIdentName是设置生成样式的命名规则。Codingcss/*components/Button.css*/.normal{/*所有与normal相关的样式*/}js//components/Button.jsimportstylesfrom'./Button.css';console.log(styles);buttonElem.outerHTML=`
