DevUI是一支兼具设计视角和工程视角的团队,服务于华为云 DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师。
官方网站: devui.design
Ng组件库: ng-devui(欢迎Star)
做为前端开发者,有些时候咱们在后端服务还未ready的时候就接到了紧急开发需求,⾯对数据接⼝的缺失和数据持久化的⽀持,开发举步维艰。固然,加班也许也是⼀种解决问题的⽅法,但若是咱们可以⾃⼰动动手指头去解决这两个问题,那么前端开发者们不只增进了对业务的了解还掌握了对数据接⼝定义的主动权,后期的联调时间成本也能够⼤⼤缩⼩。css
本文适合前端开发者阅读,阅读时长10分钟。前端
⾸先,我选⽤Vue全家桶来作这个Mock App的讲解,由于代码少、效率高。前端作数据持久化须要一个存数据的地方,有的读者可能对localstorage和sessionstorage比较熟悉,但它们的缺点以下:linux
由此可得localstorage和sessionstorage都不适合拿来解决咱们的问题,⽽WebSQL已经寿终正寝,因此只有IndexedDB可选了。git
INDEXEDDB是⼀个嵌⼊在浏览器中的事务数据库。该数据库的管理围绕JSON对象集合的概念,这相似NOSQL数据库MONGODB与COUCHDB。其中每一个对象使⽤插⼊时⽣成的键标识。⽽索引系统优化对存储对象的访问。[Wikipedia]( https://zh.wikipedia.org/wiki/Indexed_Database_API)
决定了使⽤IndexedD作数据持久化⽅案,我推荐使⽤Dexie.js对IndexedDB进⾏操做。实际上,若是没有Dexie.js这层封装,我也不会想在前端作数据mock。github
全部的⼯具已经ready,咱们将使⽤经典的message board来做为业务模型,作⼀个只关注数据层⾯的mock。数据库
先上⼀张图, Message board的业务逻辑很简单,⽤户先建立Board(帖⼦),而后此⽤户或其它⽤户在Board(帖⼦)⾥建立Message(回复)。按照正常BBS的逻辑,⽤户未登陆的时候也能够看到帖⼦,只是不能回复,这个特性也会在Mock App中体现。segmentfault
因为IndexedDB和MongoDB很类似,因此咱们能够直接将User直接保存在Message和Board的author中,⽽Message则使⽤parentId+parentType来建⽴和Board的关系。后端
使⽤Vue cli新建⼀个⼲净的项⽬,安装dexie,在src⽂件夹下新建⼀个db.ts⽂件,放⼊数据库的Schemaapi
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` })
这⾥传⼊stores⽅法的object就是数据库的schema了。 keys表明了数据库的表, value中是以逗号分隔的columns。⼀个⽐较特殊的是++id,它的意思是⾃增整形,而且它是做为表的主键存在的。其余的columns和业务剖析中的图⼀致,就不展开了。浏览器
咱们只实现最⼩可⽤的Mock App,只需实现如下⼏个API:
在本⽂最后给出的项⽬代码中有它们的具体实现。这⾥只对getUsers、 createUser和getDiscussionMessage⽅法作讲解:
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 }); }); };
这个⽅法一样返回了⼀个Promise, db.transaction中第⼀个参数是”rw”,也就是read & write的意思,由于这个createUser⽅法涉及到读数据库操做,因此它须要write access。 db.users.add({name:name})则新建了⼀⾏⽤户数据,⽤户的id被⾃动补全。
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 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://github.com/AnonymousArthur/expedited-mock
咱们是DevUI团队,欢迎来这里和咱们一块儿打造优雅高效的人机设计/研发体系。招聘邮箱:muyang2@huawei.com。
文/DevUI Arthur
往期文章推荐