Vue3企业级优雅实战-组件库框架-4组件库的CSS架构
上一篇分享了构建组件库的基础开发环境,创建了foo组件模块和组件库入口模块,这个文章分享了组件库风格的架构设计。1常见的CSS架构模式常见的CSS架构模式有很多:OOCSS、ACSS、BEM、SMACSS、ITCSS等,其中SMACSS和ITCSS非常相似。我在企业级项目中使用最多的是ITCSS+BEM+ACSS简化版,所以本文先介绍这三种模式,其他模式大家可以上网查。1.1ACSSACSS模式几乎就是一个style属性对应一个styleclass。这种方式非常灵活,复用性高,维护成本低,但破坏了CSS命名语义。常用名称如:d-flex、m-10、w-20等。1.2BEMBEM模式是一种命名方法论,其命名层次为:Block、Element、Modifier,这也是“BEM”名称的由来”。元素Element使用两个短划线(__),修饰符Modifier使用两个短划线(--),比如下面的HTML片段和对应的类名:LinkLink
使用BEM可以规范命令,页面结构比较清晰。1.3ITCSSITCSS是一种层次结构的样式。一共有七层,七层从上到下依次为:设置层:通常是一些样式变量,比如定义常用的颜色值、字体大小值等;Tools层:通用工具函数,包括mixins、functions等;Generic层:通用基础样式,一般重置浏览器的默认样式,如normalize.css、resets等库;基础层:通用一些全局使用的元素自定义样式,如页面设置、ul标签设置等;Objects层:所有使用OOCSS的地方,也就是一些结构和风格分离的特殊类;Components层:具体的组件,其实可以对应组件库中的每个组件;Trumps层:重写某些样式,比如重新设置宽度为100px,只会影响一小块DOM元素,权重最高,类似ACSS,但通常添加!important。2组件库的CSS架构ITCSS分层非常详细,我们组件库的样式就是在它的基础上进行了简化,省略了Base层或者Objects层。对于Trumps层,我们使用ACSS代替,对于Components层,里面的每个组件都使用BEM。所以我们组件库的样式架构是:ITCSS+BEM+ACSS的简化版。2.1CSS结构概述组件库的样式使用预处理器SCSS。从整体结构来看,分为以下几个层次:基础层:整个CSS结构中最基础的层次,对应ITCSS的Settings、Generic和Base。即包括变量定义、通用基础样式和自定义基础样式。tools层:和ITCSSTools一样,提供通用的工具功能。acss层:类似于ITCSS的Trumps,定义了一些原子样式类,比如flex、margin、padding相关的样式基类。Components层:同ITCSS的Components,实现各个组件的样式,各个组件的样式使用BEM方式组织命名。2.2基础层的实现前面提到,基础层包括样式变量的定义、常用的基础样式和自定义的基础样式。首先在packages/scss目录下创建一个base目录,用于存放基础层的scss文件。settingssettings是一些变量的定义,在packages/scss/base/目录下创建一个_var.module.scss文件,里面定义了样式变量。$primary-color:#488019;$common-padding:20px;:export{primaryColor:$primary-color;}GenericGeneric一般会重新设置浏览器样式,统一HTML标签在不同浏览器中的显示,屏蔽不同设备的浏览差异。这部分可以使用开源库normalize.css、reset.css等,组件库可以省略这一层,在具体应用中引入对应的css。不过程序员优雅哥还是将浏览器样式重置引入了组件库,为应用开发过程省去一些麻烦。我们使用开源的normalize.css作为Generic。normalize.css的代码可以在GitHub上搜索到。继续在packages/scss/base/目录中创建_normalize.scss文件,只需将normalize.css的内容复制到其中即可。BaseBase主要用来存放一些自定义的重置样式,比如html、body、section等,这部分我们没有自定义的内容,所以不用写。在入口文件的最后,需要将基础层中的所有scss作为一个入口统一导入。在packages/scss/base/目录下创建index.scss,导入上面创建的两个scss文件:@use"var.module";@使用“规范化”;2.3tools层的实现tools层用来存放toolsFunctions和mixins,github上有一个优秀的开源项目sassMagic,我们将其作为tools层。将项目src中的代码复制到packages/scss/tools/目录即可(如果_sassMagic.scss文件有错误,直接删除不存在文件的import即可)。这里我将_sassMagic.scss文件重命名为index.scss,这样以后使用的时候只需要@use"../tools"即可。2.4acss层的实现acss层用来定义一些原子样式。这里我们定义了flexlayout和margin/padding的原子类。在packages/scss/中创建一个目录acss,并在该目录下创建两个文件:_flex.scss和_mp.scss。packages/scss/acss/_flex.scss:.f{display:flex;}.f-c{display:flex;flex-direction:column;}.f-r{display:flex;flex-direction:row;}.f-1{flex:110;}.oy-h{overflow-y:hidden;}.oy-a{overflow-y:auto!important;}.ox-h{overflow-x:hidden;}.o-h{overflow:hidden;}packages/scss/acss/_mp.scss:$direction:(lleft,rright,ttop,bbottom);@for$i从1到30{@each$typeinm,p,v,h,a{//margin@if($type==m){@each$din$direction{.m#{nth($d,1)}-#{$i}{margin-#{nth($d,2)}:#{$i}px;}}}//填充@elseif($type==p){@each$din$direction{.p#{nth($d,1)}-#{$i}{padding-#{nth($d,2)}:#{$i}px;}}}//margin/paddingleft/right@elseif($type==h){.ph-#{$i}{padding-left:#{$i}px;右填充:#{$i}px;}.mh-#{$i}{左边距:#{$i}px;右边距:#{$i}pX;}}//margin/paddingtop/bottom@elseif($type==v){.mv-#{$i}{margin-top:#{$i}px;底部边距:#{$i}px;}.pv-#{$i}{填充顶部:#{$i}px;填充底部:#{$i}px;}}//所有@else{.pa-#{$i}{填充:#{$i}px;}}}}2.5components层的实现components层对应组件库中各个具体组件的样式,在packages/scss中创建目录components。先为上一篇创建的foo组件创建样式:在packages/scss/components/目录下创建_foo.module.scss文件:@import"../tools";@import"../acss/mp";@import"../base/var.module";@includeb('yyg-foo'){颜色:$primary-color;@includee('描述'){颜色:#333333;@延长。mv-20;}}继续在packages/scss/components/目录下创建index.scss文件,导入components目录下所有组件的scss文件:@use"foo.module";如果添加其他组件,需要在components目录下创建该组件的样式文件,并在components/index.scss中引入scss文件。2.6样式入口在packages/scss下创建index.scss,将所有scss导入其中。使用组件库时,只需导入该文件即可。@import"./acss/flex";@import"./base";@import"./components";3在组件库中引入样式最后,只需要在组件库中导入scss/index.scss即可。在组件库的入口模块packages/yyg-demo-ui/index.ts中引入index.scss:import'../scss/index.scss'(上面的代码中已经包含了这句话)至此构建完成组件库样式架构,整个样式的目录结构如下:packages/|-scss/|-acss/|-_flex.scss|-_mp.scss|-base/|-_normalize.scss|-_var.module.scss|-index.scss|-components/|-_foo.module.scss|-index.scss|-tools/|-functions/|-mixins/|-index.scss|-index.scss