红帽白皮书新鲜出炉!点击获取,让你的云战略更胜一筹! 了解详情
写点什么

ZooTeam 拍了拍你,来看看如何设计动态化表单

  • 2021-04-06
  • 本文字数:3821 字

    阅读完需:约 13 分钟

ZooTeam 拍了拍你,来看看如何设计动态化表单

前言


对于 ToB 业务而言,随着业务的不断壮大,接入的客户逐渐增加,相同页面的差异化的需求越来越多,尤其是在表单层面,小到多一个字段少一个字段这种简单的需求,大到整个页面不变的只剩下一些基础字段。


一旦这种差异化需求随着业务量的增长而膨胀起来。代码中的 IF ELSE 越来越多,项目就越来越难以维护。基于这个问题,比较普遍的解决方案要么是项目拆分,要么相同项目的代码分割。


这两种方案都有维护成本比较大的弊端,那么有没有更好点的解决方案呢。本文就带你了解一下动态化表单搭建。


什么是动态表单


先下个定义,动态表单是页面根据管理端配置的不同的 Schema 结构,动态渲染出不同的表单项的表单。


动态表单一般分两个部分,管理端和渲染端。


管理端配置表单项及相应的简单交互产出 Schema 数据。


渲染端根据 Schema 数据相应的渲染出不同的表单项并实现简单的交互。大致流程如下。



动态表单的实现


表单配置


对于 Schema 数据的配置,考虑到接入业务方的接入成本及维护成本。


管理端采用了可拖拽式的所见即所得配置面板。这里共分为四个部分,备选组件面板,拖拽面板,组件属性面板和表单属性配置(视图属性)。


具体实现如下图:



备选组件面板


左侧备选组件栏里的备选组件共分三种,容器组件,基础组件,自定义组件。


  • 容器组件——是用来存放基础组件的组件。例如表单组件,子表单组件,表格表单组件。这些组件都是内部可以存放其他子组件的组件。属于容器组件。系统内置了 3 个容器组件,对于中台系统而言,容器组件不会太多样化。所以容器组件没有做自定义组件的功能。当然后期如果需要的话也可以扩展出容器组件的自定义组件功能

  • 基础组件——就是普通的表单项。系统内置了 13 个基础组件。这些组件都是基于 Antd 的 React 组件做的二次包装

  • 自定义组件——业务方经常出现一些个性化的表单项,例如某个输入框后面加个链接跳转之类的需求,对于这种组件,系统提供了自定义组件的注册及配置功能。这样业务方就可以自由的维护专属于自己的业务表单组件了。同时也解放出表单系统维护者的时间。组件注册同时也是一个更加轻量级的自定义组件模块。因为不同的组件需要设置不同的参数,所以该组件对应的右侧属性表单也应该是不同。这部分下文组件属性部分会详细说明


拖拽面板


拖拽面板就是维护组件展示关系的面板,同时提供拖拽排序、删除、复制、预览等功能。

具体实现方案采用的是 React-DnD。


组件配置


属性配置面板本身就是个更加轻量级的动态表单实现。


只是 Schema 由开发者直接写死而没有一个可配置的页面而已(自定义组件注册部分例外)。


当在拖拽面板选中一个组件时,组件属性配置面板会渲染出相应组件的可配置项表单, 这里提供一下简单的组件属性配置面板的 Schema 供大家参考。


[{  label: '是否可见',  code: 'visible',  widget: 'switchBtn',  initialValue: true},{  label: '是否可编辑', // 标签文案  code: 'code', // 字段编码  widget: 'switchBtn', // 组件类型  initialValue: true, // 初始值 默认可编辑  hide: 'exp: visible === false', // 是否隐藏  required: true // 是否必填}]
复制代码


细心的同学会发现 hide 字段写了个表达式。这里通过 exp: 开头作为一个表达式的标识。表达式的可以使用的变量是属性表单内的值。


比如上面这个例子,visible 是上面定义了一个是否可见的字段。如果当前选中的这个组件不可见的话,是否可编辑本身就无从谈起,所以直接隐藏掉。


容器属性 共有的属性有标题、编码、是否可见、以及容器结构是否对数据透明。


前面三个好理解。容器结构是否对数据透明是什么呢?


前面说过,我们的容器组件是可多层嵌套的,那问题来了,数据咋办,表单嵌套会导致数据也跟着嵌套。所以这里参考了阿里的 Formily 开源表单方案。使用一个 skip ,来使其对数据透明。即:


{  "title": "表单",  "type": "form",  "fields": [{    "name": "name",    "label": "姓名"  }, {    "title": "子表单",    "skip": true, // 表单结构对数据透明    "name": "item",    "type": "form",    "fields": [      {        "name": "object",        "label": "物品"      }, {        "name": "brand",        "label": "品牌"      }    ]  }]}
复制代码


skip 为 false 时返回的数据为:

{  "name": "简名",  "item": {    "object": "电脑",    "brand": "Mac"  }}
复制代码


skip 为 true 时返回的数据为:

{  "name": "简名",  "object": "电脑",  "brand": "Mac"}
复制代码


组件属性 分为基本属性和组件属性,基本属性是所有属性共有的。标题,编码,是否可见,是否必填等属性都是基本属性。组件属性则是组件私有的属性。


比如 Select 组件会需要一个数据来源,以及该组件是否多选之类的。基本属性直接写死。组件私有属性则通过远程数据库维护。自定义组件的注册就需要涉及到这部分的数据管理。


自定义组件的注册表单如下:



其中组件可配置属性就是组件私有的属性的定义,注册时定义,配置该组件时赋值,渲染端渲染时应用。可配置属性还需要支持表达式的填写。


比如某个组件需要远程数据,url 提供了,但是参数需要取当前时间,这个时候就需要组件属性支持表达式的解析或者少量代码读写运行了。


这些属性除了组件自定义属性以外,还有组件默认值,组件自定义校验,组件 onChange 事件。

以自定义校验为例:



表单属性配置(视图属性)


这部分在上图中没有显示,是在组件属性右侧。表单属性分两部分,交互规则和接口绑定。



交互规则 表单交互规则在表单级别绑定,而不是在字段级别。进行就近配置的目的,是为了方便管理,进入一个表单配置,该表单的交互在右侧一目了然。


接口绑定 则是表单渲染过程中有可能涉及到一些远程数据的读取,比如默认值等。这部分数据的配置需要用到远程数据。表单上绑定了接口之后,表单初始化之前先发请求获取绑定接口的数据,相应的表单组件里就可以使用到该数据进行初始化。


管理端数据流转


管理端的功能是构建出一个目标 Schema。


每个备选组件都有基本信息和相应的组件可配置属性信息。


组件基本信息主要用于组件面板展现。组件可配置属性需要在右侧属性配置时渲染成一个表单给使用者去配置,故而组件可配置信息又是一个简化版的 Schema,这里称为组件级 Schema。


在拖拽页面中添加一个组件,通过解析组件的组件级 Schema 及组件放置位置给目标 Schema 添加一个组件数据。


然后在拖拽页面中选中该组件,右侧属性配置会相应渲染出组件级 Schema 所描述的表单给用户配置填写。用户配置时直接修改目标 Schema 中相应选中组件的信息。


数据流转图大致如下:


表单动态渲染


因为表单页面还会有各种定制化的需求,表单渲染端这里采用组件的形式,提供了两个组件,一个组件作为表单页面的外层包裹组件主要功能是发请求获取相应的 schema.json 数据。


另一个组件就是通过上层组件的数据渲染相应的表单。示例:


import { FormPageWrap, MainForm } from './index';@FormPageWrap({  prefix: '/api/budget', // 业务方接口前缀  getFormParams: (props) => { // 获取表单结构参数    return {};  },  getDataParams: (props) => { // 获取表单回填数据参数    return {};  }})export default class FormPage extends Component {  render() {    return (      <div>        // 表单各种额外显示内容        <MainForm // 表单渲染组件          customComponent={{            test: TestComp,          }}          extraParams={{}}        />        // 表单各种额外显示内容      </div>    );  }}
复制代码


内部实现则是根据 Schema 渲染相应的组件。


待完善


目前系统部分功能还有待完善。具体有几点:


  • 自定义组件的异步加载。当一个表单需要新增加一个自定义组件时,项目需要重新构建发版。如果自定义组件可以单独发布,就可以做到及时添加一个自定义组件,不需要项目重新构建发布了。当然如果自定义组件太多,异步加载还是会有些性能问题。而这就需要做到同页面下多组件代码合并了

  • 一些配置的沉淀复用。比如某些经常配置的表单块。可以沉淀为常用组件。直接选择使用,可进一步简化配置流程

  • 同页面下的一些相同区块,如果每个页面都单独维护,会极大的增加维护成本、抽取并联动,可以极大的减少维护表单的成本


展望


对于动态化表单的能力远不止目前看到的动态表单搭建:


  • 对于管理端流转出来的 Schema 数据可以进行二次加工,从而实现对于用户的权限,业务配置等能力的扩展

  • 管理端配置出来的 Schema 不止可以用在动态表单渲染中,还可以作为数据模型去描述一个静态数据的结构。从而提供各业务系统配置数据的构建能力

  • 前端渲染组件也不一定要和管理端的 Schema 完全耦合在一起。单独拿来使用也是完全没问题的,这样对于某些简化版动态表单的能力也能做到支持



头图:Unsplash

作者:简名

原文:https://mp.weixin.qq.com/s/zvegeJAOUW6tdlLUM_-Xzw

原文:ZooTeam 拍了拍你,来看看如何设计动态化表单

来源:政采云前端团队 - 微信公众号 [ID:Zoo-Team]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2021-04-06 09:452548

评论

发布
暂无评论
发现更多内容

基于实践:一套百万消息量小规模IM系统技术要点总结

JackJiang

网络编程 架构设计 即时通讯 IM

5年crud经验,三个月啃透888页Java王者级核心宝典,竟翻身阿里p6

热爱java的分享家

Java 架构 程序人生 编程语言 经验分享

微博评论高性能高可用的设计

云里雾花

react源码解析2.react的设计理念

buchila11

React React Hooks

技术解析+代码实战,带你入门华为云政务区块链平台

华为云开发者联盟

区块链 华为云 政务 Baas 异构链

深入了解Netty原理篇

邱学喆

Netty

为什么要做漏洞扫描呢?

华为云开发者联盟

安全 风险 漏洞 漏洞扫描 安全认证

数据网格简史

俞凡

架构 数据

掌握这些核心算法,拿不到10个offer你来找我,我锤你个不争气的

热爱java的分享家

Java 架构 程序人生 编程语言 经验分享

DDD领域驱动设计落地实践系列:初识DDD

慕枫技术笔记

架构 后端 签约计划第二季

写代码的思路

king

DDD与CQRS的关系

Bruce Talk

领域驱动设计 DDD

归并排序,我举个例子你就看懂了

华为云开发者联盟

算法 归并排序 序列 归并 分治法

质量基础设施“一站式”平台,NQI一站式云平台开发

电微13828808271

五面阿里拿下飞猪事业部offer,2021新鲜出炉阿里巴巴面试真题

热爱java的分享家

Java 面试 程序人生 编程语言 经验分享

系统架构性能优化思路

五分钟学大数据

11月日更

精选2021年大厂高频Java面试真题集锦(含答案),面试一路开挂

热爱java的分享家

Java 架构 面试 程序人生 经验分享

GitHub标星139K的:“嵌入式Linux系统开发教程”

热爱java的分享家

Java 架构 程序人生 编程语言 经验分享

大专毕业的我狂刷29天“阿里内部面试笔记”最终直接斩获十七个Offer

热爱java的分享家

Java 面试 程序人生 编程语言 经验分享

Hadoop 企业级生产调优手册 (二)

大数据技术指南

11月日更

网络安全是一门高级学科,如何入门,看这里!

网络安全学海

网络安全 信息安全 渗透测试 WEB安全 安全漏洞

46道史上最全Redis面试题,面试官能问的都被我找到了(含答案)

热爱java的分享家

Java 架构 程序人生 编程语言 经验分享

“退微信群”谣言背后:总有人用阴谋论湮没常识

脑极体

智慧警务系统开发,警务通app搭建

电微13828808271

不愧是阿里p8大佬!终于把Java 虚拟机底层原理讲清楚了,请签收

热爱java的分享家

Java 面试 程序人生 编程语言 经验分享

Flutter 的动画包【Flutter专题4】

坚果

flutter 签约计划第二季

Vue前端开发规范

CRMEB

Python 可以满足你任何 API 使用需求

华为云开发者联盟

Python API 程序 网络通信 公共数据

Go语言学习查缺补漏ing Day9

Regan Yue

Go 语言 11月日更

Alibaba5轮视频面:同事+组长+主管+项目+HR,收割Java岗offer

热爱java的分享家

Java 面试 程序人生 编程语言 经验分享

六年Java老鸟,写给1-3年程序员的几点建议,满满硬货指导

热爱java的分享家

Java 架构 面试 程序人生 编程语言

ZooTeam 拍了拍你,来看看如何设计动态化表单_文化 & 方法_政采云前端团队_InfoQ精选文章