1. 首页

前端快速建⽴Mock App

引言

作为前端开发者,有些时候我们在后端服务还未 ready 的时候就接到了紧急开发需求,面对数据接口的缺失和数据持久化的支持,开发举步维艰。当然,加班也许也是一种解决问题的方法,但如果我们能够自己动动手指头去解决这两个问题,那么前端开发者们不仅增进了对业务的了解还掌握了对数据接口定义的主动权,后期的联调时间成本也可以大大缩小。

本文适合前端开发者阅读,阅读时长 10 分钟。

开始

首先,我选用 Vue 全家桶来做这个 Mock App 的讲解,因为代码少、效率高。前端做数据持久化需要一个存数据的地方,有的读者可能对 localstorage 和 sessionstorage 比较熟悉,但它们的缺点如下:

  1. 缺少对结构化数据存储的优化,存取都需要调用 JSON.stringify 和 JSON.parse。
  2. 缺少对数据系统化的管理
  3. 缺少对数据查询的支持

由此可得 localstorage 和 sessionstorage 都不适合拿来解决我们的问题,而 WebSQL 已经寿终正寝,所以只有 IndexedDB 可选了。

INDEXEDDB 是一个嵌入在浏览器中的事务数据库。该数据库的管理围绕 JSON 对象集合的概念,这类似 NOSQL 数据库 MONGODB 与 COUCHDB。其中每个对象使用插入时生成的键标识。而索引系统优化对存储对象的访问。 Wikipedia

决定了使用 IndexedD 做数据持久化方案,我推荐使用 Dexie.js 对 IndexedDB 进行操作。实际上,如果没有 Dexie.js 这层封装,我也不会想在前端做数据 mock。

所有的工具已经 ready,我们将使用经典的 message board 来作为业务模型,做一个只关注数据层面的 mock。

业务剖析

先上一张图, Message board 的业务逻辑很简单,用户先创建 Board(帖子),然后此用户或其它用户在 Board(帖子)里创建 Message(回复)。按照正常 BBS 的逻辑,用户未登录的时候也可以看到帖子,只是不能回复,这个特性也会在 Mock App 中体现。

前端快速建⽴Mock App

由于 IndexedDB 和 MongoDB 很相似,所以我们可以直接将 User 直接保存在 Message 和 Board 的 author 中,而 Message 则使用 parentId+parentType 来建立和 Board 的关系。

Coding

定义数据库

使用 Vue cli 新建一个干净的项目,安装 dexie,在 src 文件夹下新建一个 db.ts 文件,放入数据库的 Schema

import Dexie from "dexie";interface DBObject {[key: string]: any;} const db: DBObject = new Dexie("myDb");db.version(1).stores({  users: `++id, name`,  boards: `++id, topic, description, author`,  messages: `++id, content, author, createdAt, parentId, parentType`})

```javascript

这里传入 stores 方法的 object 就是数据库的 schema 了。 keys 代表了数据库的表, value 中是以逗号分隔的 columns。一个比较特殊的是 ++id,它的意思是自增整形,并且它是作为表的主键存在的。其他的 columns 和业务剖析中的图一致,就不展开了。

## 定义 Mock API

我们只实现最小可用的 Mock App,只需实现以下一个 API:

+   createUser: 创建用户,用以登录应用
+   getUsers: 获取用户列表,方便我们切换用户
+   createDiscussion: 创建 Board,类似于创建一个帖子的概念
+   getDiscussions: 获取 Board 列表,类似于获取帖子列表的概念
+   getDisucssionMessage: 获取 Board 下的 Message 列表,类似于获取一个帖子下面所有回复的概念
+   createDiscussionMessage: 创建 Board 下的 Message,类似于在帖子下创建回复的回复的概念

在本文最后给出的项目代码中有它们的具体实现。这里只对 getUsers、 createUser 和 getDiscussionMessage 方法做讲解:



> Js中文网 - 前端进阶资源教程 [www.javascriptC.com](https://www.javascriptc.com),typescript 中文手册
> 专注分享前端知识,**你想要的,在这里都能找到**


```javascript

api.prototype.getUsers = function() {  return db.transaction("r", db.users, function() {    return db.users.toArray();  });};

这个方法返回了一个 Promise, db.transaction 中第一个参数是”r”,熟悉 linux 权限系统的同学肯定知道了,这是 read 权限的意思,因为这个 getUsers 方法涉及到读数据库操作,所以这个 transaction 需要 read access。 第一个传入的参数是 db.users,它声明了 transaction 将建立和 Users table 的连接,而 function 中 return 的 db.users.toArray() 则返回了 Users table 中所有的数据。


api.prototype.createUser = function(name: string) { return db.transaction("rw", db.users, function() { return db.users.add({ name: name }); });};

```javascript

这个方法同样返回了一个 Promise, db.transaction 中第一个参数是”rw”,也就是 read & write 的意思,因为这个 createUser 方法涉及到读数据库操作,所以它需要 write access。 db.users.add({name:name}) 则新建了一行用户数据,用户的 id 被自动补全。

</code></pre>

api.prototype.getDisucssionMessage = function(discussionId:number) { return db.transaction("r", db.messages, function() { return db.messages.where({ parentId: discussionId, parentType: "discussion" }).toArray(); });};
```
这个方法也返回了一个 Promise, function 中的 db.message.where 方法有点 SQL 的味道,它的作用你也猜到了,就是通过提供的过滤器(object)在 Messages table 中查询数据,然后返回所有符合过滤器筛选的结果。

定义 Vuex Store

我们会用 Vuex actions 把 API 管理起来,在 Angular 中也可以用 Service 达到同样的效果,管理起来的目的是当后端 API 开发完成的时候,我们可以很方便地迁移到新的 API 上,而不需要大量地变更已经写好的业务代码。

我们在 Vuex 的 actions 中建立和上文 Mock API 中相对应的方法,同时为了方便获取到用户登录的状态,我们可以在 getters 中加入 loginStatus,因为我们的多个层面需要判断用户是否登录,只有登录的用户才可以发言,未登录的用户只能查看讨论。

完成业务

Mock API 和 Vuex Store 都写好之后我们可以开始着手实现我们的业务逻辑。由于本身的业务实在太简单,我直接放源码了,这里不做展开。

假设我们完成了 Mock App 的编写,如何利用已完成的代码,尽量少地改动业务逻辑来适配后端的 API 呢?在 Vuex(或服务)中抽象出来的 API 就功不可没了,理想情况下我们只需要改变引入的 API 源(Angular 服务注入的时候可以用 UseClass)就能做到切换 API 的工作,因为我们的业务逻辑和 API 用什么技术方案实现的完全没关系!

事实上,基于这样的流程编写的 App 也能降低 Code Smell,促进应用与 API 的解耦,为更健壮、更具拓展性、更具可测性的 Code Base 打好基础。

总结

IndexedDB 赋予了开发者们即使没有后端的时候仍可以继续前端开发的能力,使用 Dexie 的 API 去管理 IndexDB 无疑减小了 IndexedDB 的使用门槛。同时,使用 Vuex、 Angular 这类具有服务注入能力的库 / 框架可以有效降低 API 源切换的时间成本和风险。

在前端给出需要的数据接口格式后,后端只需按要求提供相应数据即可。如果有扩展需求,只需在前端给出的接口格式上持续演进,而不用为了对接接口格式而扯皮。

在业务逻辑与 API 实现解耦之后,前端开发者可以有更多的时间去思考用户体验、编写单元测试,从而提高整个应用的鲁棒性、可用性和易用性。

最后需要强调的是,此文并不是说后端没用,因为后端提供的一些能力仍是前端远远不及的。本文的观点是,在前端做 Mock App 的这段时间内,后端可以有更充足的时间、空间去思考后端架构和实现、以更稳定的状态承载更大的总业务容量,从而为产品、公司和客户带来价值。

项目源码

链接:https://www.infoq.cn/article/ylvyvAl38uv8d36t210e

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「画漫画的程序员」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程

JS中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。欢迎热爱技术的你一起加入交流与学习,JS中文网的使命是帮助开发者用代码改变世界

本文著作权归作者所有,如若转载,请注明出处

转载请注明:文章转载自「 Js中文网 · 前端进阶资源教程 」https://www.javascriptc.com

标题:前端快速建⽴Mock App

链接:https://www.javascriptc.com/3852.html

« 六个提升前端开发效率的工具
React源码解析(一):组件的实现与挂载»
Flutter 中文教程资源

相关推荐

QR code