跳转到主文档

应用架构

上一章节中,我们把硬编码的 mockData 改成从 BFF 加载,从 App.tsx 里拆分出了 components/AllContacts.tsxcomponents/ArchivedContacts.tsx,在 AllContacts 组件里用 BFF 函数,获取到联系人数据之后,保存在 AllContacts 的组件内部状态里,而 ArchivedContacts 组件暂时继续使用 mock 数据。

本章节中,为了进一步实现项目功能,我们需要让 AllContactsArchivedContacts 都从 BFF 获取数据,还要实现【 Archive 】按钮,点击按钮能把联系人归档。

业务逻辑变复杂之后,相关代码不可避免会变多,如果都写在 AllContacts 组件或其他组件里,都会让这个组件的可读性和可维护性变差,让做不同事情的代码混在一起。

原本可以跟 UI 完全解耦的业务逻辑(比如网络请求、纯数据的操作、状态的管理等)跟 UI 逻辑(比如联系人列表如何展现)混在一起,当需要修改 UI 的时候,不得不跟 UI 无关的业务逻辑代码打交道,反过来也一样,不符合【 单一职责原则(SRP)】,也做不到【 关注点分离(SoC)】。

从这里开始,我们发现如果这是个真实的项目,继续这样写下去会产生越来越多面条式代码,仅凭 React 组件这一种抽象方式,不足以让代码足够结构化,随着项目不断积累业务逻辑、复杂性和变更,技术债也会积累,最终可能变成没人愿意碰的祖传代码。

像这样的项目,需要更健全的客户端应用架构

Modern.js 提供开箱即用的应用架构,支持几种扮演不同角色(role)、属于不同分层(layer)的代码模块类型,可以把业务逻辑解耦到不同类型的代码模块里,做到高内聚耦合

之前介绍的 App.tsxpages/ 都是其中一种代码模块,通过在最顶层对客户端路由的管理,把其他代码模块最终组织到一起,形成应用。

当前项目里 components/ 目录中的 React 组件,是一种可以称作【 视图组件 】的代码模块,负责 UI、交互上的界面展现。

本章节我们来把 AllContacts 组件中可以跟 UI 解耦的业务逻辑,移到一种叫【 Model(业务模型)】的代码模块里。