志非

V1

2022/10/17阅读:53主题:凝夜紫

记录一次《Vue 组件库开发》技术分享

前言

为了在团队推广落地组件库,让大家参与到组件库的贡献,准备了一场《组件库开发》技术分享,让大家了解组件库的搭建流程,熟悉组件库项目。

为什么造轮子?

为什么要造一个组件库轮子?毕竟这需要团队投入大量的人力和精力的一件事情。回答清楚这个问题,才能说服领导和同事们知道做这件事情的意义。

首先分析目前使用组件库的现状,对于 Element-ui 组件库来说,目前使用存在不足的地方:

  • 官方团队不在维护新增组件功能
  • 只提供基础组件,封装的方法、属性都是基本需求的,不够丰富
  • 不能定制主题和样式,不满足团队的UI规范

为了解决这个问题,团队在之前也基于 element-ui 开发了业务组件库,针对解决主题的定制和抽象封装项目中复用的业务组件,不过也存在一些不足点

  • 主题不够定制化,修改和增加一种主题,要到仓库修改源码
  • 组件部分样式不符合 UI 规范标准,使用仍然要改样式,使用成本高
  • 缺少必要规范,样式类名随意,容易覆盖影响,没有复用样式,维护成本高
  • 设计上宽松,使用一些插件用 webpack 打包,增加冗余代码,不能实现按需加载,打包项目体积大
  • 缺少在线文档和使用demo
  • 封装组件提供的功能方法少,考虑不全,丢失了 element-ui 组件部分功能,比如 table 组件

需要什么样的轮子

基于上面的问题分析,大概总结一下需要什么样的组件库轮子

  • 主题可以一键换肤,封装组件符合 UI 规范统一标准,不需要再修改样式和源码
  • 集成基础组件和业务组件,扩展组件功能和数量,提供包体积小,按需加载
  • 项目易维护,规范样式、样式隔离打包、单元测试、代码风格统一、版本更新日志等
  • 文档配套齐全,组件使用文档,在线 demo 示例代码演示
  • 拥抱社区技术,加入 Vue2.7+、Vite、TypeScript 等技术

为什么不能在原来项目基础上改造,要重复创建一个新的项目?这样不是也增加了项目的维护成本?

因为基于项目的架构、技术选型、文档使用方面的考虑,在原来的基础上改造太复杂,不太可行,所以搭建了一个新的项目,后续会将之前组件库功能迁移到新项目上,稳定后替换项目上旧的组件库,统一只需维护一个组件库。

项目介绍

介绍项目中个人认为比较重要的部分,例如架构设计、项目结构、代码规范等

整体架构

整体架构分为两部分:源码仓库和 npm 私有库

  • 源码仓库:github 或 gitlab 版本管理代码仓库,统一维护组件源码、组件使用说明、开发文档、在线demo演示等

  • npm 私有库:托管静态资源,管理组件库 npm 包,提供下载源

源码架构设计

单包架构

优点

通过相对路径实现组件与组件的引用,公共代码之间的引用。

缺点

组件完全耦合在一起,每次改动都需要一起打包发布,不能单独下载

所以,选择使用单包架构的话,为了减少包的体积,需要提供按需加载的能力

多包架构

优点

  • 每个 package 包彼此独立,单独打包发布,单个仓库多个包
  • 无需配置实现按需引用和加载
  • 关注点分离,包之间解构,结构清晰,容易维护

缺点

组件与组件之间物理隔离。对于相互依赖,公共代码,只能通过 NPM 包引用的方式来实现。

目标项目使用的是单包架构,考虑到未来业务组件越来越多,进行多包架构升级,容易维护,参考 element-plus 目录设计

技术栈

  • 框架&库 Vue2.0、Element-UI
  • 主题换肤 CSS 自定义属性和 SCSS
  • 开发环境 Vite
  • 打包构建 rollup、gulp
  • 代码规范 husky、lint-staged、commitlint、eslint、prettier
  • 文档主题 vuepress、webpack

项目结构

  • build:rollup 构建打包配置文件
  • config:项目配置文件
  • docs:基于 vuepress 主题文档
  • examples:基于 vite 项目开发环境
  • packages:组件核心包文件
  • scripts:文档部署等脚步文件
  • src:项目入口文件
  • styles:组件样式文件目录

代码规范化

  • husky:执行 git-hooks 钩子,检查代码规范,常用 pre-commit,commit-msg

  • lint 校验代码: ESlint,Prettier,Stylelint 检查和修复代码格式,统一代码风格

  • commitlint:对 commit messag 进行校验,符合 Angular 团队规范

  • lint-staged:配合 husky,每次提交时只检查本次提交的暂存区的文件

  • 更新日志: standard-version 自动生成 CHANGELOG 版本功能更新日志

自定义主题换肤

组件库基于 element-ui 实现,换肤要考虑两个方面,分别对 element-ui 和 组件库的样式进行换肤

1、Element-ui 组件库换肤

实现方式:加载 element-ui 样式文件,通过正则匹配替换主题颜色

2、组件库换肤

实现方式:利用 CSS 自定义属性 和 SCSS 变量定义主题颜色, 通过 element.setProperty 修改主题颜色

CSS 自定义属性

全局CSS自定义属性

:root 对象定义属性和属性值,属性名需要以两个减号(--)开始,由 var() 函数来获取值

组件局部CSS自定义属性

为了避免全局覆盖影响,参考 element-plus 设计,组件局部重新定义 CSS 属性,创建局部作用域

样式资源隔离

抽离组件 SASS 样式和变量文件,统一管理样式资源,方便样式复用和维护拓展,然后使用 gulp 打包压缩样式字体资源

开发流程

组件库贡献流程详细步骤

1、fork 项目仓库:https://github.com/JefferyXZF/douluo-ui

2、克隆项目仓库到本地,安装依赖

3、develop 是开发分支,基于该分支创建功能分支,例如 feat-button

4、阅读开发文档,熟悉组件开发规范

5、根据 UI 规范设计和实现组件功能

6、组件测试,编写测试用例和组件说明文档

7、使用 npm run commit 代替 git commit,提交符合 commit-msg 规范

8、发起 PR 合并前,合并 devleop 分支避免冲突,通知相关人 code review 合并代码

9、更新版本号和日志,打包发布更新 npm,更新项目组件库依赖包

组件开发

组件设计原则

组件库的开发不同于一般的业务组件开发,考虑到组件的拓展性和维护性,需要遵循一些设计原则

单一职责:根据功能拆分组件,且组件粒度不宜过细,前提是复用

组合性:将多个单一职责的小组件组合成为一个职责更大、功能单一的组件,比如时间选择组件是由选择组件、输入组件等组合而成;

封装性:隐藏内部细节和实现意义,并通过props来控制行为和输出(单向数据流)

可测试:一个组件不易于测试,很大可能是组件设计存在问题

组件设计五要素

在实现组件前对组件进行设计,根据功能进行分析,考虑以下几个要素

  • 对外扩展属性 - props

  • 自身状态 - data

  • 事件 - event

  • 方法 - methods

  • 子视图插槽 - slot

以 button 组件为例

组件实现

  1. packages 目录创建组件文件,编写实现逻辑
  2. 在 src/ui 引入创建组件文件,对外暴露注册组件
  3. styles/src 创建样式文件,common/var.scss 定义组件变量
  4. styles/src/index.scss 引入组件样式
  5. compoments.json 定义组件路径打包入口

未来计划

项目升级

  • 多包架构

功能迭代

  • 单元测试
  • 组件按需加载
  • 抽象补充业务组件数

技术升级

  • vitepress 文档提高打包速度
  • TypeScript 保证代码质量
  • Vue2.7+ 和 JSX 灵活组件开发

分类:

前端

标签:

前端

作者介绍

志非
V1