【项目总结】Vite+Vue3+TS组件库my-element-plus
之前发现了一个非常好的学习项目,技术栈很新,于是就学习了一下思路,自己实现了一遍。果然,人还是得逼着自己,最近的学习节奏还算不错,再做完项目后来总结一下,编写并完善文档,这不就形成了一套解决方案吗?尽管这只是一个较简单的项目,很多复杂组件还未加入,但其中的思路还是很有启发性的。
项目地址:https://github.com/Fridolph/my-element-plus
my-element-plus 学习相关组件及源码,仅供学习参考
文档地址:https://fridolph.github.io/my-element-docs/
起步
所谓万事开头难,在决定好技术栈后,最重要的就是进行项目构建。Vue3 + Vite 一把梭确实爽!
- eslint
- postcss
- vitest 直接可用
- volar
- vite
- vitepress
相关依赖安装好后,直接按官方推荐设置 vite.config.ts 即可
根据经验,在做这种组件库项目时我发现可能需要花费更多时间(当然也可以使用 TDD 测试驱动开发)。但我更喜欢先把组件开发完成再去补充测试……理清需求和目的,逐步实现,效果会更好。
目录结构
对于这种项目,推荐的最佳实践是直接照搬大型开源项目的目录结构。当然,由于这个项目相对小且简单,也可以更加灵活一些,去掉那种复杂的模块结构,按照组件进行分类即可。
配色参考
色彩 - 组件设计前重要的一环。
中国色
https://peiseka.com/zhongguochuantongse.html
bootstrap
https://getbootstrap.com/docs/5.3/customize/color
tailwind.css
https://tailwindcss.com/docs/customizing-colors
可以将颜色先写到 styles 里的变量中,现在更推荐 CSS 的变量
styles > var.css
之前一直用 scss、stylus ,现在原生 css 已经很强大了,浏览器支持也很好,所以我们直接用 css vars
兼容性肯定要做的, autoprefixer 不可少,所以还是上 PostCSS。它是一个功能比较单一的工具,它提供了一种方式用 JavaScript 代码来处理 CSS。它负责把 CSS 代码解析成抽象语法树结构(Abstract Syntax Tree,AST),再交由插件来进行处理。
编写一个组件
如:Button - 按钮。大概是按以下思路来进行的
需求分析
Button 组件大部分关注样式,没有其他交互。可在其上自行绑定事件
根据分析,暂得以下具体属性列表:(button.type.ts)
- type 样式
- plain
- round
- circle
- disabled
- icon
- loading
确定项目文件结构:
- 从简单入手,这里就都放到 components/Button 下了
- Button(components) 后续组件都参照这个文件结构来
- Button.vue
- style.css
- types.ts
- Button.test.ts
- 以学习为主没必要过度设计,过于纠结细节
- 该组件是否能完成基本功能
- 是否需要暴露实例 或 expose 属性或方法等
编写测试代码:
- 测试基本功能展示 OK
- 传递 prop 后能否正常展示
- 测试交互事件能否触发
总结遇到的一些问题:
- 编码过程遇到的 bug
- 样式能否实现
- 其他实现方式 (锦上添花)
每当完成一个组件,应立即更新 vitepress 对应的组件文档:
一个组件文档工作量很少,且能有效反馈让进度可控,一定要坚持。一旦堆多了,后期反而文字类工作才是让程序员最头大的
表单组件
感觉这里总结得还成,就写到博客里了。
表单是用户和网站交互最重要的一部分。
表单有很多控件,这里选了几个简单的模拟实现,就单独整理写到这里了. 表单包含 输入框, 单选框, 下拉选择, 多选框 等用户输入的组件。 使用表单,您可以收集、验证和提交数据。
典型表单:
最基础的表单包括各种输入表单项,比如:
- input
- select
- radio
- checkbox
在每一个 form 组件中,你需要一个 form-item 字段作为输入项的容器,用于获取值与验证值。
按照原型图整理的简单需求:
- 自定义 UI
- 整理可自定义
- 用户可自定义渲染多种类型的表单元素
- 用户可自定义提交区域内容
- 验证时机
- 表单元素默认 blur 时验证,可自定义
- 整个表单在点击提交时应全部验证
- 验证规则
- 每个 input 可配置多条规则
- 规则可自定义
组件结构设计
1 | const formOptions = { |
但这种用法过于繁杂,不灵活,在使用上体现不出结构,会让 js 臃肿,所以用 slot 的形式
1 | <form :options="formOptions" /> |
开发步骤:
- 根据结构,实现基础布局,完成 demo
- 添加初始化数据,绑定数据
- 添加验证
- 事件交互,验证等
- 不断完善
实现验证功能的思路
验证类型:
- 表单 Form 整体验证
- 单个表单 FormItem 的验证
表单中每项循环验证一次 every 即为表单验证结果
单个验证实现思路:
- 从父组件 Form 获取对应 option、value
- 在 FormItem 组件中实现
第三方库:async-validator
关于打包
为什么要打包?
- 模块化
- 可维护性
- 可复制性
模块化定义:以功能块为单位进行程序设计,实现其求解算法的方法称为模块化。模块化的目的是为了降低程序复杂度,使程序设计、调试和维护等操作简单化。
打包什么类型的文件
- CommonJs, ES6 modules 需要特殊的打包工具支持
- AMD 已过时
- 浏览器直接使用 (UMD)Universal Module Definition(但不支持 tree shaking)
- 通用 JS 格式
- 兼容 Common.js、AMD、浏览器
综上:
首要格式 - ES Module ,并且提供支持 TypeScript 的 type 文件
备选方案 - UMD
lib 相关设置
对应 vite.config.ts 中需要设置 build.lib 相应类型(参考文档配置即可)
我们可为每个组件建立一个 index.ts ,例如 Button
1 | import type { App } from 'vue' |
在src和main.ts同级目录下新建一个index.ts用来导入组件,将各组件注册到Vue实例中,这样打包出来就可通过import形式导入了
1 | const components = [ |
发布遇到的坑
最近 npm 淘宝源 证书过期了,所以得改地址 = = 之前老是遇到依赖安装问题,都是这些小问题造成的,一不注意会卡很久
1 | npm config set registry https://registry.npmmirror.com |
但在发布时需要登录npm 又得把淘宝源去掉
1 | npm config set registry https://registry.npmjs.org |
npm login 登录不上 - - 困扰很久,结果发现是网络问题,手机开热点,电脑连手机的,登npmjs就可以了,发布完记得改回来。
最后
虽然看起来很简单,但折腾了几周才终于搞定。实际上,大部分时间花在改样式和配置上,而真正完成功能反而挺快的。本来也想试试TailWindCss,但发现还有些应对不了的问题,于是干脆改到了履历项目里(是的,先挖个坑告诉自己必须填)。
加油,2024!只要行动起来,就是好的开始。