vue下表单场景的思考

1,625 阅读9分钟

vue下表单场景的总结与思考

问题与思考

最近在网上看到了一篇阿里的开源文章:【中后台应用】从表单抽象到表单中台;引起了很深共鸣和思考,文中其实是提出了一种动态表单(也可称为数据配置表单)的解决方案,开发者通过这套方案,由(写页面(组件)+写状态=>表单)转变为配置生成表单,思路与主轴十分明确。

作为面向toB业务的前端,表单场景几乎是日常开发标配,无论业务大小,或多或少都会参与开发类似与工单系统之类的数据录入系统,这类系统常常要求将表单发挥到极致,开发者需要兼顾前端样式与交互,同时还要处理繁杂的嵌套数据与业务逻辑。

从技术角度讲,开发表单它存在什么技术难度嘛?与开发脚手架插件、开发组件、开发web(移动端)应用甚至性能调优来比对,总感觉在心中差了那么一节,认为它就是纯粹的在堆砌业务,甚至遇到的问题业界早已有成熟的应对方案,长时间的开发这种系统,很容易被场景束缚住,形成思维定势;那么它就一点技术难度都没有嘛?每每开发这种业务的时候,内心都十分难受,每一个细节都需要增加状态去控制,接口传递的几十个上百个字段要一一记住,但总结下来无外乎几种常见的case。

比如交互上的表单项与表单项的联动(校验)、表单项与层之间的联动(校验)、层与层之间的联动(校验);数据上的状态回溯(重置或tree shaking)、字段或数据集之间的映射与组装、浅拷贝或引用传递等等。

如果有一些业务沉淀的话,也会走上配置生成表单的道路,比如拿到一个表单时,配置一个json schema,然后循环解析这个json schema去适配不同的组件,如果是用vue的话,还可以自定义双向数据绑定来收集数据集。从系统搭建之后,这种组件我从不同的纬度重构了很多次,但限制于技术或眼界因素,从没有离开过这个路子。

在这个过程中,随着业务的加重,慢慢暴露了很多问题。

1.可维护性问题:如果解析器与渲染组件杂糅在一起的话,随着场景的增多,渲染组件需要接入更多的基础组件来适配,同时还要针对特殊的组件扩展json schema字段。这样解析器与渲染组件变得臃肿不堪,一旦更换组件库或者更换项目会出现严重的‘水土不服’。

2.单向数据流问题:这个问题与Vue框架息息相关,与Angular不同,Vue在集成指令之后,走向了react单向数据流动的路子,这个问题本质是子组件的状态向上收敛由父组件接管控制。但对于表单场景,双向数据流动基本是'刚需',父组件需要收集子孙组件反馈的各种数据,子孙组件需要录入改写父组件传入的对象。虽然vue针对表单场景支持了双向数据绑定,使得一部分问题得以解决,但也会引出另一部分问题(如下)。

3.浅拷贝与引用传递:这个问题也可以归咎于开发者自身,当传入自组件的props深层次对象,如果该对象是由父组件动态挂载属性的话,那么子组件也可以通过动态挂载属性来改写传入的对象,造成双向数据的假象,虽然视图可能会动态更新,但这样做副作用很多,比如难以维护,响应式更新时灵时不灵。

4.性能问题:处理表单对象时,很可能会使用深度watch的方法来收集子数据集的变化,或者来实现双向数据绑定,这就意味着,如果你的渲染组件循环机制处理不当的话,每次表单项变动都会重绘整个表单。另外,当需要对数据进行业务处理的时候;比如表单项固定接受数组类型,而db只接受非数组类型(不考虑db对更改),这时候就需要对数据进行转换与映射,这样对逻辑会贯穿表单增删改查始终(想想就十分心痛);还有另一种方式 ,把表单项包一层(高阶组件),在双向数据流侧完成数据的转换与映射(props->子组件->非数组; 子组件->input->数组),这个过程同样存在问题,如果处理不当,会引起vue响应式机制的死循环。

5.可维护性:通过json配置表单的方式固然能够缩减表单页面的开发时间,但常见的场景里,页面效果并不占多少开发时间,大头常常在交互效果、数据处理、联动及校验的处理上,这时组件状态的复杂度随业务的增长而增长。过多的json处理与状态会增加开发者的维护成本。

6.可复用性:我们知道,json schema只是一种形式,其本质依然是实例化封装的基础组件,刨除组件库 提供的组件,我们也会沉淀自己的业务组件,但问题在于,谁能保证封装的业务组件能适用后续的业务发展呢,我们为该组件定制了一套json schema,当后续不适用的时候,会面临,想抛抛不调,想改就是重构的这种问题。同时,对于公共组件的开发者同样有要求,需要对toB场景有丰富的经验最好。

7.开发效率:我们提出配置开发表单这个模式就是为了提升开发表单的效率 。但对于vue框架来讲,只面向json就意味者需要将指令封装进基础组件,或者其他hack方法来达到交互效果。这个问题其实就是,当前端不能通过json来配置表单时,如何允许前端通过template声明式来书写组件,如果支持插槽,如何处理属性、事件的透传。

同时,声明式组件依然存在另外的问题,比如表单操作的feed back或蒙版中的表单,这种场景其实只是一次性消费的表单,如果支持命令式通过js调用会更能节省开发效率。

8.设计风格:这块仅仅是我个人的想法。当对表单进行校验时,我需要给表单项包上<form> <form-item>(大多数组件库表单场景提供的机制),同时还要通过prop来追踪表单项的属性,然后再去定制校验规则。这套机制其实非常适合通过声明式方法去开发。它是从一个整体(form)来设计表单的,与原生表单思想谋合。但我仍旧觉得非常繁琐,为什么不能将校验封装进表单项中呢,为什么不能状态分布式下发至组件中呢。

我们知道,渲染组件需要接入很多配套的基础组件,我们可以把渲染组件看作整体,基础组件看作部分。整体是由部分搭建而成,那么哪些状态是由整体负责的,哪些可以下发至部分?如何区分界限?如果状态提升至整体处理,如何接入扩展机制?如果状态下发至部分管理,如何降低基础组件开发门槛?如何节省开发效率,等等。

select组件举例,option可以是下拉项组件,那可以支持option集成进select中吗?

以上是在开发表单场景中遇到的问题与思考。

如何去解决

json to view

对于表单场景的解决方案有很多,比如final-form, YourForm, vue-form-generater, vue-create, UForm, Amis等等。这些都是非常优秀的表单场景解决方案。

其中Final-form是基于react的表单解决方案,它的思路与主轴很清晰:

1.json schema构建及渲染模版。

2.副作用对立管理,统一处理所有的表单字段,自动拼接数据路径。

3.组件间通过发布订阅机制实现通信。

通过以上的库,基本上可以实现json+模版的方式快速开发表单场景。但这仍然不够,想一想,如果你每周需要开发一堆列表页、一堆表单页(增删该查一系列),即使不再重复造轮子,这种重复工作的场景也会令人十分痛苦。

可视化or自动化

作为开发者,遇到上述问题时,会很自然去尝试使用工具自动生成template或者json(连json都不想配置)。但又会遇到新的问题,这样的工具在初始化时用处很大,那二次开发或者需求变动时如何支持呢?代码生成了,通用的业务逻辑和数据处理可以方法生成并自动绑定吗?除了维护一套渲染器,还需要维护一套生成器。

可视化可以使自动化提供的能力更强大,但可视化系统的开发难度很难控制,它面向谁?开发、产品、UI/UE?不同的用户,可视化系统的支持程度不一样,产出也不同,并且它的开发门槛也会占用开发者较长的开发时间。

表单中台

可视化搭建页面的这种系统,几乎每个公司都有,也很有必要性,但能完美适配三大框架生态的较少。

如何去设计一个表单中台?

image

从表单抽象到表单中台详细的作出了整个表单中台的详细架构设计,因为是基于React生态,所以针对Vue生态设计的表单中台要对前端解析器作出相应更改。

前端方面,关于如何针对Vue框架,Vue组件去做相应设计,如何去设计json schema,如何去编写解析器,如何设计解析器扩展机制,如何开发组件通信机制,以及如何开发渲染器及配套渲染组件等问题,本文不做深入探讨。接下来的我会围绕提出的这些问题及机制逐一的调研,一个环节一个环节的解决与分享。