通用前端架构设计(整洁架构+领域划分)(vue3版)(草稿)

4,142 阅读6分钟

只是草稿

技术方案

  • 依赖技术
    • TypeScript
    • Vue3
    • Vue-Router
    • Vue-CLI
    • Vant-UI(v3)
    • Less
    • TailwindsCss
    • Axios
  • 架构模型
    • 分层架构
    • 整洁架构
    • 领域驱动设计

设计原则

分离关注点SOC

分离关注点(separation-of-concerns)

image-20210309151446088

image-20210309151458033

image-20210309102536599

单一职责SRP

单一职责并不是说:一个函数只做一件事。虽然那也是一种设计原则,但并不是现在说的单一职责。

历史上对SRP有很多不同的解释,我挑个好理解的:

任何一个软件模块都应该有且仅有一个被修改的原因1

该原则具体到本文实践有状态管理和架构依赖管理等。

以状态管理举例:

就像Redux或Vuex中,我们只能通过dispatch一个action这种方式来修改数据。那么State(软件模块)只能被Actions(修改的原因)修改。

image-20210310123120249

本项目代码的hooks返回的数据也是不可修改的,有且仅能通过dispatch特定的操作才能修改。

image-20210308212502689

读写分离CQS

读写分离(Command Query Separation)。

这个原则最多被运用在API的设计上,Command 用来表示一些会修改数据的方法,比如列表

  • 用户1:hansheng
  • 用户2:tamir

现在我们想往这个列表添加一个新用户(写操作),此时后端会给我们一个addUsers的接口,我们执行

addUsers([{name:'juily'}])

这个时候我们来思考这个接口要不要有返回值呢?

我们会觉得我执行完这个接口,然后后端直接返回一个UsersList,我们就可以很方便渲染,比如:

// 错误方式!!!
const ret = await addUsers([{name:'juily'}])
console.log(ret.data) // [{name:'hansheng'},{name:'tamir'},{name:'juily'}]

然而,这么做是不对的,这个原则就是说这件事的,正确的方式应该是:添加完后,我们发起一个查询操作(读操作):

await addUsers([{name:'juily'}])
const ret = await queryUsers()
console.log(ret.data) // [{name:'hansheng'},{name:'tamir'},{name:'juily'}]

具体到本项目中,就是我们在写用例的时候,会有modlesdispatch,其中的dispatch就是一个写操作,而models就是一个读操作。

image-20210309102419763

:warning: 注意: 这里的getInformation对应到restful-apis可能就是一个读操作,但是在我们的用例中,做这个请求,是拿到后端数据后,对models进行一种更新,即写操作。

架构模式

image-20210308201526538

本次项目没有接入测试功能,待后续再添加

用户界面User interface

image-20210308200455251

视图View

本文提到的View层,统一表示为:CSS+HTML最后渲染到浏览器的视图。

所谓的View层,在现在的Web开发已经交由视图框架去处理了,即开发中我们所书写的Vue的<tempalte>或者React的JSX,他们都是归属于Presentaion层,他们代替我们手动的去修改真实的DOM结构。在开发中,我们也应该尽量不去操作真实的DOM。

这里单独提出这个层主要是介绍本项目的:

  • 移动端适配方案
    • rem
    • viewport
  • 使用的样式方式
    • less预处理
    • tailwindcss样式工具库
  • UI组件主题定制
    • vant
  • 设计稿
    • 蓝湖
HTML移动端适配

本项目共存两种适配方案

rem方案

image-20210309105430290

manage/路由的,是以前对外的静态站点,当时只使用了rem来完成,具体开发的时候需要自己去计算rem等操作,也存在页面变动时要重新计算等缺点。

所以为了让后续可能逐渐复杂的移动版管理系统更好开发,在manage/下的页面均使用vp方案

vp方案

在使用上使用了postcss-px-to-viewport

删除了东西

CSS样式
Pre-Processors:less

和别的项目保持一致使用less

如果有需要配置及修改的需求,自行查阅 Vue CLI文档

tailwind css(可选项)

image-20210309113938707

如果在项目中看到tw-开头的就是使用了tailwindcss提供的样式。

这个为可选项,如果不喜欢的话,请忽略

tailwindcss是一个类似Bootstrap的样式工具库。

image-20210309114413385

如果想使用tailwindcss需要注意我做了配置修改

  • 添加了tw-前缀
  • 单位:比如在蓝湖给的px单位数值是多少,在映射到tailwindcss时直接输入对应的值就可以了

如果要使用请下载对应的插件

image-20210309114857125

这样就会自动跳出提示,不然每次都去打tw-前缀可太麻烦了。

image-20210309115000768

UI组件库

vant(V3)组件库

image-20210309125055847

注意:本项目使用的是V3版本,因为默认是进入V2版本。

主题定制

这里我已经引入并配置了好全部主题的变量及默认值。

image-20210309125028893

如果有主题修改的需求,自行到图中文件进行修改,这种方式修改是热更新的,很方便的。

image-20210309125233362

如果主题修改无法满足特定的样式需求且需要全局复用该样式的话,就到上图中的components目录进行对应的组件样式修改。

如果有涉及到对组件的全局的样式修改,一定要统一放这里,不然不好定位样式问题。

如果不是全局的,仅单个或几个页面中的时,记得在样式的修改一定要限制在对应的页面中,如:

image-20210309131543452

展示器Presentation

Vue组件

  • 绑定事件
  • 数据校验(暂定如此)
  • 路由跳转
  • 获取用户输入
  • 展示数据

业务逻辑Application core

image-20210308200249916

领域服务Domian Services

就是对业务的拆分,比如现在mopen的业务就两个领域服务

  • 账户
  • 产品

image-20210309151705909

不同的领域服务下有对应的用例集

用例Use Case

image-20210309151748513

以用户领域来说,对应的用例就有

  • 登录
  • 修改密码
  • 获取验证码
  • 。。。

所谓的用例就是:数据+方法

  • modles
  • dispatch

具体使用方法请阅读:Vue-Reactivity实现状态管理(Redux、Vuex)

哈哈哈 还没写

基础设施infrastructure

image-20210308200259068

  • http请求
    • axios
    • BaseAPI
    • config:src\config\api.ts
  • cookie (JWT)
    • 登录鉴权
  • router
    • 权限:src\shared\infra\router\index.ts
  • 工具集
    • 校验函数
  • 公共组件

开发规范

Git开发流程

详情请阅读:Git工作流与规范

Eslint规范+代码风格

详情请阅读:ESlint+Prettier+EditorConfig+VScode

常见脚本

  • 开发环境
  • 生产环境打包
  • 本地开发中连接项目环境
    • 待整理

TODO

  • 监控
    • 性能
    • 上报
  • 测试
  • 图片优化
    • svg组件
    • 压缩
  • 接口类型自动生成
    • yapi
  • git规范使用脚本限制
    • git-comment
    • git-hooks
  • 打包优化
    • 剔除无用代码的生成和引入
    • vant样式

参考

Footnotes

  1. 《架构整洁之道》