最近接到一个表单自动保存的需求,一开始以为只是简单的数据保存,抄起键盘就干,十行代码不到实现个大概的:
1 | setInterval(() => { |
看需求是要pc端和app端同步,好像也不难,只是把保存到localStorage的过程改成保存到服务端,但是实际做起来问题倒是挺多的。
Q: 实现的基本思路
A: 项目一直尝试MVC模式,也有一点DDD的味道。所以虽然pc端和app端有很大的差异,但是模式差不多,表单一般都由一个具体的表单模型去驱动。所以基本的思路是,pc端和app端分别是两个不同的model,那就基于这两个model去抽离出一套通用的数据格式。
然后基于这份数据格式,存的时候pc和app转换成该数据格式,拉取的时候又分别根据这份数据转换为自己需要的格式存到model里。
除了存的这些格式外,还需要做一套接口,比如某个字段变动之后,会调用接口去异步查询,或者某几个字段有联动。比如支付金额超过4000万,且支付币种为美金时需要调接口去查询是否需要拆单。
有了基本的思路就开始实现了…
Q: 一些组件不是瓦全由数据驱动的,有一些是行为触发,所以你数据一致并不能百分百的还原当时的组件状态。
A: 对这个问题,没有特别好的办法,属于历史留下的包袱,解决的方法就是直接去改造这个组件。因为这些其实属于一个bug,只是以前一直没有这种 time travel 的场景,所以没有被发现。
Q: 一些数据属于临时状态,业务表单的时候不需要提交到服务端,但是他又会影响到一些业务判断。
A: 把这些数据也存起来,可以在 getSaveData() 的时候手动给他拼接进去。
Q: 一些字段有联动,比如字段改动后回触发异步请求去校验,或者拉取其他的新数据。
A: 封装一套工具,做一些通用的hook,比如每个字段填充之前调用接口,自定义填充方式,全部填充后调用一些初始化的接口等等。配置大致可以如下:
1 | { |
但是最好的做法还是在 pc和 app统一一套支付的model,然后在model层做,这才是我认为的最优解。把业务无关的抽离成模型去框架化,这样不管你用的是angular,react还是vue都可以公用一套,这对于我们项目来说是非常实用的。不过由于诸多历史包袱,现在还没有实现,但是已经在路上了。