3.组件表设计


id:
wordId                  # 组件名称,国际化后得到componentName
outputs         jsonb   # 当前组件有哪些输出,基本上一个文本框就算一个输出
params          jsonb   # 当前组件自己决定怎么使用这些参数,支持传递常量值、context中的值
datasources     josnb   # 当前组件需要哪些数据源
helpInfoWordId          # 组件级别的帮助信息
describe                # 该字段使用markdown语法,主要用于表述该组件的文档

outputs字段如何设计的

我目前设计的是,组件中一个文本框就代表一个outputs,在表单设计器中,outputs必须绑定到属性上,后端存储表单设计数据时也会进行该项检查。我组件设计时参考了一些金数据,我也想提供组件级和字段级别的帮助信息,所以output的结构如下:


{
    outputs: [{
        "outputName":"output1",
        "outputType":"",        # 支持String、Integer、Boolean
        "helpWordId":"xxxId"
    }]
}

outputName是参数级别的东西,我不考虑其国际化了,但是帮助信息还是需要支持国际化的,所以我使用了helpWordId,这些都是我存储的结构,我返回给前端的时候,还是会根据language替换成相应的提示信息。

我考虑了一段时间后,决定增加outputType类型字段,output是组件当前上下文中重要的数据,当output绑定了属性后,属性会成为表单上下文中重要的数据,这些上下文中的数据会应用到自己即其他组件的params、datasouce parms区域。这些区域都要求都要求进行数据类型检查。

params字段怎么用

我在调研金数据的时候,我发现金数据的部分组件的右侧设计底部都有一排小小的checkBox来配置一些组件的细微行为,如下图所示:

2021-05-16-12-40-53

我觉得这个是有意义的,所以我也提供了params,我们暂时不会提供金数据那种非常友好的操作小界面,而且说明部分一般都是通过组件库中的文档进行说明的。

另外,这个params更有意义的地方在于:它可以绑定context中的值,组件从而可以通过它实现组件间的联动。

params应该是尽量提供默认值的,如果组件强烈需要将context中的值绑定到自己的params中,从而减少组件对表单上下文环境的猜测,我们应该需要强制用户填写这个参数的。故params的配置如下:


{
    params:[{
        "paramName":"param1",
        "defaultValue":"13",
        "type":"integer",           # 目前这个地方支持的值有:Integer、String、Boolean(表单设计器需要支持对此的检查)
        "require":"true"            # 是否必填项(表单设计器需要支持对此的检查)
        "tips":"wordId"             # 提示信息(未来我们也想实现金数据的那种效果)
        "exploreLocation":"params"  # 暴露在哪个区域,这个也是为了实现金数据而设计的字段,值可以为params(参数区)、config(配置区),目前组件设计中,右侧还没有配置区,配置区就是类似金数据的右下角
    }]
}

params字段在填值的时候,是支持通过下拉框从表单上下文、组件上下文中选取值的,但是它又同时支持用户直接填一些常量值,我没有想好这块输入框怎么设计,可以交给产品,这个属于体验级别的东西了。

datasources字段设计


{
    datasources:[{
        "datasourceName":"xxx数据源",
        "returnType":"StringList",
    }]
}

看到这块的结构,我自己也在怀疑组件声明数据源就这么简单,能满足高级的需求吗?先看看我自己的左右互搏吧。

»>以下内容仅做讨论,不推荐该方案«<

假如啊,我不要用户去给我搞什么绑定,假如啊,组件在调用数据源的时候,一定是按照组件喜欢的方式去调用的,行不行。我先告诉你,肯定是可以的,我动态表单的第一套设计就是这个方案。我给你构思下完整的场景,组件直接通过如下的伪代码的方式声明自己要的数据源具备的特点:


datasources:
    datasource1:
        param1 String
        param2 Boolean
        param3 Integer
    datasource2:
        param1 String
        param2 Boolean
        param3 Integer

当在表单设计器中,选择数据源的时候,小小的选择框就会通过这些条件去我们的数据源库查找所有符合条件的数据源,然后用户选择一个添加进组件编辑区域。置于要用到的context参数,我们在params区域完成绑定。置于绑定的这些context如何被传递到了数据源,完全是由组件自己决定的。

为什么我放弃了这个方案了?~~~你们感觉这个像什么,像不像方法的覆盖,组件中定义的是一个抽象方法,组件中绑定的是一个具体的实现。既然像方法的覆盖,那么它们的问题就是(我不从技术上讨论了,意义不大)~~~因为组件本身还是高度定制的啊,用这种方案实现的一个下拉框组件,怎么去实现组件间的联动呢。难道我很还需要去开发一个下拉框组件(二级)、下拉框组件(三级),这让用户怎么去理解啊?核心的原因就是调用数据源的方式,被组件给自己控制了,那数据源本身就没有高复用的可能性了。

»>讨论完毕«<

在新设计中,我就只想简单点,主要数据源的返回值都是一致的,我就可以为这个组件提供数据。在这种场景下,我还考虑了两个问题:

  1. 数据源很清晰的知道我自己需要哪些参数,能够返回那种类型的数据结构给到用户。而且你要你提供了这些参数,那么就一定可以拿到相应的数据。
  2. 组件很清晰的知道数据源该怎么使用,它根本就不需要数据源的概念,它只需要一个url而已。

这个我在数据源设计中也讨论过,这个就是高通用的组件和高度定制的组件。我其实建议就走两个极端,我们要么开发高通用的,要么开发高定制的。更极端一点,开发高定制的时候,我们甚至不需要声明数据源,前后端开发直接将url写在在组件里好了。如果组件需要表单上下文的参数,就通过params区域获取。

如果,未来我们有需求,将某个组件给通用化,我们可以一步一步的做,我们可以先将url写到数据源中,从而实现替换不同的数据源,使这个组件出不同的数据。然后将params区域,原本用来获取context中的数据的param放到数据源的reqeustBody中,这样更优雅一些。接下拉,我们将检查源也从硬编码的组件中给剔除来。其实要做的工作真的没有多少。

我是建议这部分在整个系统使用中慢慢总结,慢慢优化的。