在前一篇文章中分享了搭建组件库的基本开发环境、创建了 foo 组件模块和组件库入口模块,本文分享组件库的样式架构设计。

1 常见的 CSS 架构模式

常见的 CSS 架构模式有很多:OOCSSACSSBEMSMACSSITCSS 等,其中 SMACSSITCSS 很相似。我在企业级项目中最常使用的是简化版的 ITCSS + BEM + ACSS,所以本文首先介绍这三种模式,其他模式大家自己上网查看。

1.1 ACSS

ACSS 模式几乎是一个样式属性就对应了一个样式类。这种方式非常灵活,复用性很强、维护成本低,但破坏了 CSS 命名语义化。常见的名称如:d-flex、m-10、w-20 等。

1.2 BEM

BEM 模式是一种命名方法论,其命名层级为:Block元素 Element修饰符 Modifier,这也是 “BEM” 这个名字的由来。元素 Element 使用两个短下划线(__),修饰符 Modifier 使用两个短中划线(--),如下面的 HTML 片段和对应的类名:

<div class="demo-block">
<a class="demo-block__element1">Link</a>
<a class="demo-block__element1 demo-block__element1--modifier">Link</a>
</div> <style>
.demo-block {} // 块
.demo-block__element1 {} // 元素
.demo-block__element1--modifier1 {} // 修饰符
</style>

使用 BEM 可以规范命令,页面结构也比较清晰。

1.3 ITCSS

ITCSS 是一种样式的分层结构,一共有七层,七个层次从上到下依次为:

  • Settings 层:通常是一些样式变量,如定义通用的颜色值、字体大小的数值等;
  • Tools 层:通用工具函数,包括 mixins、function 等;
  • Generic 层:通用基础样式,一般是对浏览器默认样式进行重置,如 normalize.css、resets 等库;
  • Base 层:对某些全局使用的元素进行通用的定制化样式,如页面的设置、ul 标签的设置等;
  • Objects 层:所有使用 OOCSS 的地方,即某些结构和样式相分离的专用类;
  • Components 层:具体的组件,其实可以对应到组件库中的每个组件;
  • Trumps 层:重写某些样式,如 width 重新设置为 100px,只会影响某一小块的 DOM 元素,权重最高,类似 ACSS,但通常会加上 !important

2 组件库的 CSS 架构

ITCSS 分层非常细致,咱们组件库的样式在其基础上进行了简化,省略了 Base 层 或 Objects 层。而对于 Trumps 层,咱使用 ACSS 来替代,对于 Components 层,里面的每个组件内部又使用 BEM。所以咱们组件库的样式架构为:简化版的 ITCSS + BEM + ACSS。

2.1 CSS 结构概览

组件库的样式使用预处理器 SCSS,从结构整体来看,分为如下层级:

  • base 层:整个 CSS 结构的最基础的层级,对应了 ITCSS 的 Settings、Generic 和 Base。即包括变量定义、通用基础样式和定制基础样式。
  • tools 层:与 ITCSS 的 Tools 一样,提供通用工具函数。
  • acss 层:类似 ITCSS 的 Trumps,定义一些原子样式类,如 flex、margin、padding 相关的样式基础类。
  • components 层:与 ITCSS 的 Components 一样,实现各个组件的样式,其中每个组件的样式又使用 BEM 方式来组织命名。

2.2 base 层的实现

前面说过,base 层包括样式变量定义、通用基础样式、定制基础样式。

首先在 packages/scss 目录下创建 base 目录,存放 base 层的 scss 文件。

  1. settings

settings 是一些变量的定义,在 packages/scss/base/ 目录中创建 _var.module.scss 文件,该文件定义样式变量。

$primary-color: #488019;
$common-padding: 20px; :export {
primaryColor: $primary-color;
}
  1. Generic

Generic 通常是对浏览器样式的重置,统一 HTML 标签在不同浏览器中的展示,屏蔽浏览器间的差异。在这个部分可以使用开源库normalize.cssreset.css 等。这一层可以在组件库中省略,在各个具体的应用中引入对应css。不过程序员优雅哥还是将浏览器样式重置引入到组件库中,这样应用开发过程中省点事。咱使用开源的 normalize.css 作为 Genericnormalize.css 的代码可以在 GitHub 上搜索获取。

继续在 packages/scss/base/ 目录中创建 _normalize.scss 文件,将 normalize.css 的内容直接复制进去就可以了。

  1. Base

Base 主要是存放部分重置样式的自定义,如 html、body、section 等,这部分咱们暂时没有自定义的内容,就无需编写了。

  1. 入口文件

最后需要将 base 层所有 scss 以统一的入口引入。在 packages/scss/base/ 目录下创建 index.scss,该文件导入上面创建的两个 scss 文件:

@use "var.module";
@use "normalize";

2.3 tools 层的实现

tools 层用于存放工具函数和 mixins,github 上有个优秀的开源项目 sassMagic,咱们就使用它作为 tools 层。

将该项目 src 中的代码拷贝到 packages/scss/tools/ 目录下即可(如果 _sassMagic.scss 文件中有报错,将里面对不存在文件的引入删除即可)。我在这里将 _sassMagic.scss 文件重命名为 index.scss,这样后面在使用时只需要使用 @use "../tools" 即可。

2.4 acss 层的实现

acss 层用于定义一些原子样式,这里咱们定义 flex 布局和 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: 1 1 0;
}
.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: (l left, r right, t top, b bottom);

@for $i from 1 through 30 {
@each $type in m, p, v, h, a {
// margin
@if ($type == m) {
@each $d in $direction {
.m#{nth($d, 1)}-#{$i} {
margin-#{nth($d, 2)}: #{$i}px;
}
}
}
// padding
@else if ($type == p) {
@each $d in $direction {
.p#{nth($d, 1)}-#{$i} {
padding-#{nth($d, 2)}: #{$i}px;
}
}
}
// margin/padding left/right
@else if ($type == h) {
.ph-#{$i} {
padding-left: #{$i}px;
padding-right: #{$i}px;
}
.mh-#{$i} {
margin-left: #{$i}px;
margin-right: #{$i}px;
}
}
// margin/padding top/bottom
@else if ($type == v) {
.mv-#{$i} {
margin-top: #{$i}px;
margin-bottom: #{$i}px;
}
.pv-#{$i} {
padding-top: #{$i}px;
padding-bottom: #{$i}px;
}
} // all
@else {
.pa-#{$i} {
padding: #{$i}px;
}
}
}
}

2.5 components 层的实现

components 层对应组件库中每个具体组件的样式。在 packages/scss 中创建目录 components。首先为上一篇文章中创建的 foo 组件创建样式:在 packages/scss/components/ 目录下创建 _foo.module.scss 文件:

@import "../tools";
@import "../acss/mp";
@import "../base/var.module"; @include b('yyg-foo') {
color: $primary-color; @include e('description') {
color: #333333;
@extend .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'

(在上文中的代码已经包括这一句引入了)

到此便完成了组件库样式架构的搭建,整个样式的目录结构如下:

感谢你阅读本文,如果本文给了你一点点帮助或者启发,还请三连支持一下,点赞、关注、收藏,程序员优雅哥会持续与大家分享更多干货

Vue3 企业级优雅实战 - 组件库框架 - 4 组件库的 CSS 架构的更多相关文章

  1. Vue3 企业级优雅实战 - 组件库框架 - 1 搭建 pnpm monorepo

    前两篇文章分享了基于 vite3 vue3 的组件库基础工程 vue3-component-library-archetype 和用于快速创建该工程的工具 yyg-cli,但在中大型的企业级项目中,通 ...

  2. Vue3 企业级优雅实战 - 组件库框架 - 3 搭建组件库开发环境

    前文已经初始化了 workspace-root,从本文开始就需要依次搭建组件库.example.文档.cli.本文内容是搭建 组件库的开发环境. 1 packages 目录 前面在项目根目录下创建了 ...

  3. Vue3 企业级优雅实战 - 组件库框架 - 2 初始化 workspace-root

    上文已经搭建了 pnpm + monorepo 的基础环境,本文对 workspace-root 进行初始化配置,包括:通用配置文件.公共依赖.ESLint. 1 通用配置文件 在项目 根目录 下添加 ...

  4. Vue企业级优雅实战04-组件开发01-SVG图标组件

    (后续的文章 公众号会提前一周更新,欢迎关注文末的微信公众号:程序员搞艺术) 预览本文的实现效果: # gitee git clone git@gitee.com:cloudyly/dscloudy- ...

  5. Vue企业级优雅实战-00-开篇

    从2018.1.开始参与了多个企业的中台建设,这些中台的技术选型几乎都是基于 Spring Cloud 微服务架构 + 基于 Vue 全家桶的前端.我前后端架构及开发我几乎各占一半的精力,在企业级前端 ...

  6. CSS框架分析与网站的CSS架构

    框架(framework)是一个基本概念上的结构,用于去解决或者处理复杂的问题,是一种可复用的构架. 我们对CSS框架这个词比较陌生,但对于JavaScript框架就比较熟悉了,比如jQuery 但为 ...

  7. Vue企业级优雅实战05-框架开发01-登录界面

    预览本文的实现效果: # gitee git clone git@gitee.com:cloudyly/dscloudy-admin-single.git # github git clone git ...

  8. Vue企业级优雅实战03-准备工作04-全局设置

    本文包括如下几个部分: 初始化环境变量文件 JS 配置文件初始化:如是否开启 Mock 数据.加载本地菜单.URL 请求路径等: 国际化文件初始化:初始化国际化文件的结构: 整合 Element UI ...

  9. Vue企业级优雅实战02-准备工作03-提交 GIT 平台

    代码管理.版本管理是件老大难的事情,尤其多人开发中的代码冲突.突击功能时面临的 hotfix 等.本文只是简单说说如何将一套代码提交到两个 Git 平台(GitHub.GitEE)上.其他的 Git ...

随机推荐

  1. 【Java】学习路径53-InetAdress获取服务器ip

    InetAdress如何使用? import java.net.*; public class InetAdress { public static void main(String[] args) ...

  2. Mybatis中多对一与一对多

    多对一的处理 在pojo中就有 Student private String name; private String id; private Teacher teacher; 比如说多个学生对应着一 ...

  3. [网鼎杯 2020 朱雀组]phpweb-1|反序列化

    1.打开界面之后界面一直在刷新,检查源代码也未发现提示信息,但是在检查中发现了两个隐藏的属性:func和p,抓包进行查看一下,结果如下: 2.对两个参数与返回值进行分析,我们使用dat时一般是这种格式 ...

  4. day01-GUI坦克大战01

    JavaGUI-坦克大战 1.Java绘图坐标体系 坐标体系介绍:下图说明了一个Java坐标体系.坐标原点位于左上角,以像素为单位.在Java坐标体系中,第一个是x坐标,表示当前位置为水平方向,距离坐 ...

  5. k8s 网络持久化存储之StorageClass(如何一步步实现动态持久化存储)

    StorageClass的作用: 创建pv时,先要创建各种固定大小的PV,而这些PV都是手动创建的,当业务量上来时,需要创建很多的PV,过程非常麻烦. 而且开发人员在申请PVC资源时,还不一定有匹配条 ...

  6. Homework6

    1.问:阅读和了解什么是形式化方法? 答:形式化方法在逻辑科学中是指分析.研究思维形式结构的方法.是把各种具有不同内容的思维形式(主要是命题和推理)加以比较,找出各个部分相互联结的方式,抽取出共同的形 ...

  7. Job And Schedule (V8R6C3)

    KingbaseES 数据库提供了 kdb_schedule 扩展,使得用户能通过类似oracle job 的方式进行job调用.kdb_schedule 提供了三个Schema :dbms_job ...

  8. DFS算法-求集合的所有子集

    目录 1. 题目来源 2. 普通方法 1. 思路 2. 代码 3. 运行结果 3. DFS算法 1. 概念 2. 解题思路 3. 代码 4. 运行结果 4. 对比 1. 题目来源 牛客网,集合的所有子 ...

  9. winform,xml读取与写入

    创建两个xml文件,一个 xml做为模板配置项,另一个做为临时接收数据. private static string localPath = System.Environment.CurrentDir ...

  10. 【全网最全】springboot整合JSR303参数校验与全局异常处理

    一.前言 我们在日常开发中,避不开的就是参数校验,有人说前端不是会在表单中进行校验的吗?在后端中,我们可以直接不管前端怎么样判断过滤,我们后端都需要进行再次判断,为了安全.因为前端很容易拜托,当测试使 ...