Vue3 企业级优雅实战 - 组件库框架 - 4 组件库的 CSS 架构
在前一篇文章中分享了搭建组件库的基本开发环境、创建了 foo 组件模块和组件库入口模块,本文分享组件库的样式架构设计。
1 常见的 CSS 架构模式
常见的 CSS 架构模式有很多:OOCSS、ACSS、BEM、SMACSS、ITCSS 等,其中 SMACSS 和 ITCSS 很相似。我在企业级项目中最常使用的是简化版的 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 文件。
- settings
settings 是一些变量的定义,在 packages/scss/base/ 目录中创建 _var.module.scss 文件,该文件定义样式变量。
$primary-color: #488019;
$common-padding: 20px;
:export {
primaryColor: $primary-color;
}
- Generic
Generic 通常是对浏览器样式的重置,统一 HTML 标签在不同浏览器中的展示,屏蔽浏览器间的差异。在这个部分可以使用开源库normalize.css、reset.css 等。这一层可以在组件库中省略,在各个具体的应用中引入对应css。不过程序员优雅哥还是将浏览器样式重置引入到组件库中,这样应用开发过程中省点事。咱使用开源的 normalize.css 作为 Generic。normalize.css 的代码可以在 GitHub 上搜索获取。
继续在 packages/scss/base/ 目录中创建 _normalize.scss 文件,将 normalize.css 的内容直接复制进去就可以了。
- Base
Base 主要是存放部分重置样式的自定义,如 html、body、section 等,这部分咱们暂时没有自定义的内容,就无需编写了。
- 入口文件
最后需要将 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 架构的更多相关文章
- Vue3 企业级优雅实战 - 组件库框架 - 1 搭建 pnpm monorepo
前两篇文章分享了基于 vite3 vue3 的组件库基础工程 vue3-component-library-archetype 和用于快速创建该工程的工具 yyg-cli,但在中大型的企业级项目中,通 ...
- Vue3 企业级优雅实战 - 组件库框架 - 3 搭建组件库开发环境
前文已经初始化了 workspace-root,从本文开始就需要依次搭建组件库.example.文档.cli.本文内容是搭建 组件库的开发环境. 1 packages 目录 前面在项目根目录下创建了 ...
- Vue3 企业级优雅实战 - 组件库框架 - 2 初始化 workspace-root
上文已经搭建了 pnpm + monorepo 的基础环境,本文对 workspace-root 进行初始化配置,包括:通用配置文件.公共依赖.ESLint. 1 通用配置文件 在项目 根目录 下添加 ...
- Vue企业级优雅实战04-组件开发01-SVG图标组件
(后续的文章 公众号会提前一周更新,欢迎关注文末的微信公众号:程序员搞艺术) 预览本文的实现效果: # gitee git clone git@gitee.com:cloudyly/dscloudy- ...
- Vue企业级优雅实战-00-开篇
从2018.1.开始参与了多个企业的中台建设,这些中台的技术选型几乎都是基于 Spring Cloud 微服务架构 + 基于 Vue 全家桶的前端.我前后端架构及开发我几乎各占一半的精力,在企业级前端 ...
- CSS框架分析与网站的CSS架构
框架(framework)是一个基本概念上的结构,用于去解决或者处理复杂的问题,是一种可复用的构架. 我们对CSS框架这个词比较陌生,但对于JavaScript框架就比较熟悉了,比如jQuery 但为 ...
- Vue企业级优雅实战05-框架开发01-登录界面
预览本文的实现效果: # gitee git clone git@gitee.com:cloudyly/dscloudy-admin-single.git # github git clone git ...
- Vue企业级优雅实战03-准备工作04-全局设置
本文包括如下几个部分: 初始化环境变量文件 JS 配置文件初始化:如是否开启 Mock 数据.加载本地菜单.URL 请求路径等: 国际化文件初始化:初始化国际化文件的结构: 整合 Element UI ...
- Vue企业级优雅实战02-准备工作03-提交 GIT 平台
代码管理.版本管理是件老大难的事情,尤其多人开发中的代码冲突.突击功能时面临的 hotfix 等.本文只是简单说说如何将一套代码提交到两个 Git 平台(GitHub.GitEE)上.其他的 Git ...
随机推荐
- 【Java】学习路径53-InetAdress获取服务器ip
InetAdress如何使用? import java.net.*; public class InetAdress { public static void main(String[] args) ...
- Mybatis中多对一与一对多
多对一的处理 在pojo中就有 Student private String name; private String id; private Teacher teacher; 比如说多个学生对应着一 ...
- [网鼎杯 2020 朱雀组]phpweb-1|反序列化
1.打开界面之后界面一直在刷新,检查源代码也未发现提示信息,但是在检查中发现了两个隐藏的属性:func和p,抓包进行查看一下,结果如下: 2.对两个参数与返回值进行分析,我们使用dat时一般是这种格式 ...
- day01-GUI坦克大战01
JavaGUI-坦克大战 1.Java绘图坐标体系 坐标体系介绍:下图说明了一个Java坐标体系.坐标原点位于左上角,以像素为单位.在Java坐标体系中,第一个是x坐标,表示当前位置为水平方向,距离坐 ...
- k8s 网络持久化存储之StorageClass(如何一步步实现动态持久化存储)
StorageClass的作用: 创建pv时,先要创建各种固定大小的PV,而这些PV都是手动创建的,当业务量上来时,需要创建很多的PV,过程非常麻烦. 而且开发人员在申请PVC资源时,还不一定有匹配条 ...
- Homework6
1.问:阅读和了解什么是形式化方法? 答:形式化方法在逻辑科学中是指分析.研究思维形式结构的方法.是把各种具有不同内容的思维形式(主要是命题和推理)加以比较,找出各个部分相互联结的方式,抽取出共同的形 ...
- Job And Schedule (V8R6C3)
KingbaseES 数据库提供了 kdb_schedule 扩展,使得用户能通过类似oracle job 的方式进行job调用.kdb_schedule 提供了三个Schema :dbms_job ...
- DFS算法-求集合的所有子集
目录 1. 题目来源 2. 普通方法 1. 思路 2. 代码 3. 运行结果 3. DFS算法 1. 概念 2. 解题思路 3. 代码 4. 运行结果 4. 对比 1. 题目来源 牛客网,集合的所有子 ...
- winform,xml读取与写入
创建两个xml文件,一个 xml做为模板配置项,另一个做为临时接收数据. private static string localPath = System.Environment.CurrentDir ...
- 【全网最全】springboot整合JSR303参数校验与全局异常处理
一.前言 我们在日常开发中,避不开的就是参数校验,有人说前端不是会在表单中进行校验的吗?在后端中,我们可以直接不管前端怎么样判断过滤,我们后端都需要进行再次判断,为了安全.因为前端很容易拜托,当测试使 ...