FormRender 开源第二弹:一站式表单解决方案

15,264 阅读8分钟

Github: github.com/alibaba/for…,支持开源项目的发展,欢迎到 Github 点 Star!

本文旨在介绍 Form Render (FR)这个阿里开源表单解决方案。简述它想解决的问题,我们的理念和解法,这半年走过的路,以及 FR 的未来规划

未来

放眼不久后的未来,表单的开发体验会是怎么样的?

  1. 上传一张表单的截图,识别生成可用代码,让旧系统的迁移如梦一般迅速

  2. 所见即所得的表单设计器,拖拖拽拽完成表单的开发。并可自由定制成符合自身喜好的独特设计器

    image-20200904163844008
  3. 一个聚合所有上述工具的开发平台,在其上你可以统一的维护和存放表单,生成对应存放地址,在业务上投放只需一个url

    // 请求统一平台,获取对应的展示
    <FR url={"https://..."} />
    

这个未来其实以近在眼前。FormRender 目前对2、3的支持度已经到 90%

一体化的开发体验

目前的FR开发模式如下图:

从设计稿 -> 到表单设计器 -> 产出schema -> 贴入代码直接可用。目前这条链路是 FR 的“黄金”开发模式。加上详尽的文档在线playground以及新功能Demo的示例,上手成本足够低,完成一个繁杂的表单需求,快的只需要1个小时(起脚手架,复制一下demo代码,用设计器生成表单schema)。

初衷

看到这里,可能你已经对 form-render 有了大致的体感,但对“协议搭建“的顾虑和疑问并没有消除:这只是一个demo吧,

  1. 实际开发复杂度有多高?
  2. 能支持复杂场景么?能支持联动么?
  3. 能支持多样化的定制需求么?

答案都是肯定的。在回答这几个问题前,我们简单介绍一下 FR 的初衷和设计思考:

FormRender(下面一律简称 FR)起源于 2017 年飞猪互动平台的模板表单生成方案。当时的互动平台有大量模板开发需求,产出的模板需要开放给运营进行在线化的配置和投放,对于开发者,他们不仅要开发组件,还要产出平台的配置表单。我们给出了第一套方案,开发者只需要在组件的props上写好注释,平台侧表单就自动生成了:

在开发体验上这是质得飞跃。我们明白这个小小的 form-render 走对了路。FR 经历 2 年在飞猪内部以及集团兄弟 BU 各个场景的落地和打磨,于 2019.09.30 月开源 v0.1.0 版本,目前迭代到 v0.8.2,star 1.5k, fork 157,npm 月下载量 2k

FR 目前覆盖了飞猪内部玩法平台、互动平台、搭建、投放、批量智能生产、众多频道管理等小二平台,是飞猪的官方表单方案。在开源期间支持了集团内阿里云团队淘宝社区团队淘宝新零售团队阿里人工智能实验室安全智能部下 10+个 BU,20+个场景的搭建、配置后台和投放系统。下图是一些 FR 的使用场景:

搭建在阿里是一波大潮,但个人在维护FR时感受要真正设计好用且易上手的搭建体系并非易事,或者说,需要取舍。这里简单分享一下个人在设计上的一些思考:

设计思考

思考1:配置 vs 组件

FR 的核心是用 JSON 配置的方式代替组件化的开发。配置和组件都是对事物的抽象,事实上组件也是配置的一种(组件的props就是配置项),本质上它们的区别在于封装的粒度

从组件的角度:手写过表单的同学都知道,哪怕是最简单的两个框的表单你都无法避免要去写 “胶水函数” 即校验和提交等,是个比较费时的活,且反复的需求中想通过复制黏贴来完成复用其实也挺有难度的。

但切换到配置的角度:表单和外部的交互集中在了提交这个唯一出口,所以胶水层的校验、联动以及对复杂组件的支持都是相对方便用属性方式描述的。这导致表单场景天然适合配置。

思考2:规则化的协议

有了上传的表单设计器后,协议schema层已经被弱化了,但如何制定一个稳定且可扩展的协议仍然是搭建里几乎最重要的一环。FR的协议遵循了几个简单的约定:

  1. 主体上继承 JSON schema 国际标准 不另起炉灶,JSON schema能描述到大部分的表单基本信息和校验,例如title、description、enum、default、format 和 pattern 等

  2. 所有元素通用的展示描述,使用 "ui:xxxx" 描述。例如 "ui:disabled": true

  3. 只有某些表单元素需要的展示描述,全部放在 "ui:options"

在这三条标准下,FR从第一版开始,协议层的改动都是增量的,确保了使用方不会出现大幅的版本迁移工作。

思考3:如何做到极简

FR的口号是:像写一个 input 一样写一个 form

一个 React 的可控 input 如下

<input value={this.state.value} onChange={this.onChange} />

一个 FR 的表单如下,保持了最简单的使用api

<FormRender
  schema={schema} // 描述表单UI
  formData={this.state.value}
  onChange={this.onChange}
/>

可控模型对于用户来说更清晰:提交 = 从state里取值,操作表单 = setState,再也不用去文档里找无数的提交api和操作api。

思考4:复杂场景的解法

回到刚才的问题:

  1. 实际开发复杂度有多高?
  2. 能支持复杂场景么?能支持联动么?
  3. 能支持多样化的定制需求么?

这是刚才抛出的几个问题,当然答案都是肯定的。下图很好地说明了 FR 如何处理定制化的需求(你想用一个 <MyInput /> 的手写组件来渲染表单的输入框):

至于联动,这里分享一个前几天群里小伙伴们提问的时候放出的schema。我还从来没有写这么长过~

image-20200904172234291

有兴趣了解的小伙伴们,在文档的如何联动以及自定义组件模块都给出了详细的讲述和Demo。

FR 二期做了什么

  • FR一期的重点在基础协议的功能支持 & UI展示的优化。我们敲定了schema的扩展方式,敲定了联动和自定义组件的方案,并支持了海量业务对接中提炼出的共性需求。

  • FR二期在进一步扩展schema的同时,重点从FR本身转移到了协议接入侧。FR的一大痛点(或者说大多数同类解决方案共通的痛点)在于schema手写上手成本高且易错。我们提供了表单设计器这个桥梁,并以此为基础在搭建的路上尝试也了一波。放在FR大图里,二期做的事主要集中在蓝色的块:

未来规划

FR的现状和未来有一段 gap:

  1. 目前我们只给出一站式开发的基本能力,但这个闭环上还有很多的不完善
  2. 用户在复杂场景积累了不少诉求,还有不少事要解
  3. 开源项目的发展需要更多人的参与,我们开放的口子以及给开发者的体验还是欠佳的
  4. 随着使用场景的复杂化,对FR本体的能力会有各种各样的需求和挑战

所以我们未来一年的规划的重点在两趴:

  1. 向上往搭建延伸,完善这个开发体验的闭环,这里包括
    • 表单设计器的完善,允许各种形式的定制。让用户真正能够以fr-generator为基础定制一份自己项目的表单设计器
    • 统一的schema存放和投放平台
    • 自定义组件接入的明确入口
    • 以及往AI识别方向的探索
  2. FR本身功能和性能的提升
    • 联动、校验的更全面支持,且统一到函数式的解决方案(目前校验不支持函数表达)
    • 复杂场景确保用户体验,性能上的提升和优化
    • JSON schema高级用法的对齐,ui:schema更多实用功能的扩展

下图在每一块里用蓝色标注的规划要做的事儿

我们希望在一年后:

  • 轻量用户可以参考在线demo和完备的配置文档快速搭起FR的代码,完成表单需求
  • 中度用户可以通过表单设计器拖拖拽拽生成表单协议,并无缝的产出代码
  • 重度用户可以通过平台统一管理和投放schema,统一的查找和开发自定义组件的入口,以满足定制需求
  • 迁移用户可以通过一张现有系统的快照生成对应的FR代码,轻松迁移(当然复杂场景肯定是需要一定的手动成本的)

最后

很喜欢乔布斯的一句话:“Life can be so much broader, once you discover one simple fact: that everything around you that you call 'life' is made up by people no smarter than you. And you can change it, you can influence it, you can build your own things that other people can use.”

翻译成中文就是说,FR 说到底就是一个 React 组件,代码壁垒极其低。当你对 FR 有什么不满时,意识到自己完全可以进来贡献两行代码哈~ 欢迎各位的拍砖、issue、以及进钉钉群聊聊 。

github:github.com/alibaba/for… 官网:x-render.gitee.io/form-render… 表单设计器:x-render.gitee.io/schema-gene… 钉钉群: