当前位置: 首页 > Web前端 > CSS

前端进阶(一)——CSSModularity

时间:2023-03-31 11:28:19 CSS

{`.container{color:blue;}p:first-child{color:red;}.hello{color:yellow;}#hi{color:green;}`}CSS模块化CSS(CascadingStyleSheets),从诞生之初就被确定为不能编程,甚至不是解释型语言。它只能作为一个简单的用于格式化HTML元素的层叠样式表。但是随着前端的发展,前端项目变得越来越大,越来越复杂,社区一直在探索如何管理前端代码(js/css/html)和资源(图片,字体,...).在这个过程中,社区探索了js(amd、commonjs、es6)的模块化,现在用js开发大型项目很容易,但是css的模块化一直不是特别流行。1.分组模块化这是CSS模块化最早实现的,也是最主要的方式,包括现在很多组件和开发者都是采用这种方式开发的。分组模块化就是采用命名的方式,不同的前缀代表不同的含义,达到样式分组的目的,将文件分块,从而达到模块化的目的。例如:#目录结构|--one/page/css/某个页面的css目录|--common.csscommoncss|--page1/singlepage1|--section1.cssarea1css|--section2.cssarea2css|--page2/singlepage2|--...#common.css文件.c-el-1{...}.c-el-2{...}...#page1/section1.css文件.page1-section1{...}.page1-section1.el-1{...}.page1-section1.el-2{...}...#page1/section2.cssFile.page1-section2{...}.page1-section2.el-1{...}.page1-section2.el-2{...}...这种方式不是真正的模块化,因为问题全局冲突无法避免,但是原生css不具备编程能力,所以这个问题无法避免。虽然分组不是真正意义上的模块化,但是这种方式并没有脱离css的原生机制,所以很多第三方组件,尤其是导出css文件的时候,都是采用这种方式。比如ant-design导出的css中使用了ant-前缀,mui导出的css中使用了mui-前缀,等等。1.1最佳实践css的命名和分组实践由来已久,自从css诞生以来,所以社区发展的非常成熟,比如网易的css规范框架NEC、H-ui。补充:一个css文件不要太大,可以使用@import来分割文件;样式渲染尽量不要使用#id[attr],尽量使用.class;使用js库操作dom时,尽量不要使用.class,尽量使用#iddata-set,如$('#main'),$('[data-tab="1"]')。

    tab1tab2
1.2css语言扩展因为css不是编程语言,不能声明变量、函数、判断、循环和计算,也不能嵌套,所以这使得写作风格成为一项低效且乏味的工作。为了解决这个问题,社区在探索中主要衍生出了两种扩展语言less和sass。它们兼容css,扩展了编程功能。它们主要带来以下特点:可以声明变量和函数,以及一些简单的计算、判断和循环;选择器可以嵌套,节省了书写内容,可读性更强;.page1-section1{....el-1{....el-1-1{...}}.el-2{...}}@import避免重复导入问题,所以你可以导入其他充满信心的文件。从模块化的角度来看,less和sass只是扩展了css的功能,并没有在语言层面做模块化,因为全局命名冲突的问题依然存在。2、模块化(导出为js对象)要让css具有真正的模块化功能,暂时不能从语言层面考虑,只能从工具的角度来实现。目前比较好的方法是用js加载css文件,将css的内容导出为一个对象,用js渲染整个dom树,然后将相应的样式匹配到相应的元素上,在这个过程中,我们有机会对css做额外的处理,达到模块化的目的。例如:sourcefile#style.cssfile.className{color:green;}#jsfileimportstylesfrom"./style.css";element.innerHTML='你好!
';实际效果#style.cssfile._23_aKvs-b8bW2Vg3fwHozO{color:green;}#DOMHello!
在这个转换过程中,根据文件的位置和内容生成一个全局唯一的base64字符串来代替原来的名字,避免了全局命名冲突的问题,从而达到模块化的目的。所以在开发过程中不存在全局样式冲突的问题。#common.cssfile.container{...}.el1{...}.el2{...}...#page1/section1.cssfile.container{...}.title{...}.content{...}...#page2/section1.cssfile.container{...}.title{...}.content{...}...参见css-了解css模块化的定义modules,这里写css的要求主要是:.class不能用#id[attr](因为只有.class才能导出为对象的属性);建议写成.className而不是.class-name(前者可以通过styles.className访问,后者需要styles['class-name']才能访问)。有关更多功能,请参阅css-modules。当然这个功能需要构建工具的支持。如果使用webpack构建项目,可以使用css-loader并将options.modules设置为true以使用模块化功能。3、模块化(内置js,绑定组件)随着前端组件化的发展,react、vue等组件化框架的更新,慢慢发展到将整个组件的资源封装起来,只对外暴露一个对象外部世界,调用者不需要关心组件的内部实现和资源,直接调用这个对象即可。例如(以react为例),一个Welcome组件包括一个js文件,一个css文件,一张图片:#Welcome组件|--welcome.js|--welcome.css|--images/可以在welcome.js加载如下(使用“exportasjsobject”css模块化):importstylesfrom'./welcome.css';从'./images/1.jpg'导入image1;其实还有另外一种思路,那就是把css构建成js,成为js的一部分。这样做的目的是将css模块化,直接绑定到组件上。比如material-ui、styled-jsx、jss、vuestylescoped都是这样使用的。有很多方法可以实现这个方法。这里主要介绍styled-jsx。3.1styled-jsxstyled-jsx的原理是根据当前文件的位置和内容生成一个全局唯一的标识符,然后将这个标识符附加到组件的每个元素和每个样式选择器上,以达到模块化的目的。可以参考官方文档查看详细使用方法。我这里举个例子:3.1.1安装工具(babel转码需要)npminstall--savestyled-jsx3.1.2配置babel插件(比如.babelrc){"plugins":["styled-jsx/babel"]}3.1.3添加源文件代码hello.jsexportdefault()=>(Hello!Hello!

嗨!{`.container{color:blue;}p:first-child{color:red;}.hello{color:yellow;}#hi{color:green;}`})3.1.4转码babelpath/to/hello.js-dtarget/dir转码文件import_JSXStylefrom'styled-jsx/style';exportdefault()=>(你好!你好!

嗨!<_JSXStylestyleId={"234963469"}css={".container.jsx-234963469{color:blue;}p.jsx-234963469:first-child{color:red;}.hello.jsx-234963469{color:yellow;}#hi.jsx-234963469{color:green;}"}/>);3.1.5运行实际渲染效果.container.jsx-234963469{color:blue;}p.jsx-234963469:first-child{color:red;}.hello.jsx-234963469{color:yellow;}#hi.jsx-234963469{color:绿色;}你好!你好!

你好!4.关注更多博文,查看https://github.com/senntyou/blogs作者:沈育之(@senntyou)版权声明:免费转载-非商业-非衍生-署名保持(CreativeCommons3.0许可)