在中后台系统中,通常有大量的表单填写的流程,一般常见的流程是:

  1. 抽象制定 Schema 来定义表单信息
  2. 基于 Schema 构建渲染器来渲染表单
  3. 扩展 Schema 和维护通用表单组件

基于这个流程,自制定一套也没什么技术难度,但是要沉淀出一套适合业务并易于扩展的 Schema 规则并不容易。

社区有很多优秀的方案,为什么选用的是Formily?

在调研时,首先要评估业务的需求场景是否满足。

例如一个常见的业务场景,当选项,选择企业时,输入企业相关信息:

1
2
3
【身份】:[]个人 [] 企业

【企业名称】:请输入

其他方案大多只停留在UI的渲染映射层面,无法快速定制业务的联动。

而 Formily 通过属性响应则可以快速实现表单间的简单业务切换。

字段联动

下面是基于 Formily 的一些搭建及应用介绍。

Formily

相关链接:

由于 designable 设计器已经停止维护,下面是一个较为活跃的 Fork 分支。

designable 表单设计器

安装依赖

具体参见官网,仅供参考

1
yarn add @formily/core @formily/element @formily/vue

通用组件

基于官网文档,稍微改造一点,得到一个通用的基于Schema渲染的Vue组件。

1
2
3
4
5
6
<template>
<FormProvider :form="form">
<SchemaField :schema="schema" />
<Submit @submit="onSubmit">提交</Submit>
</FormProvider>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<script>
import { createForm } from '@formily/core'
import { createSchemaField, FormProvider } from '@formily/vue'
import * as AllForm from '@formily/element'
const { Submit } = AllForm
import EntForm from './ent-form.json'

const schema = EntForm.schema

const form = createForm()
const fields = createSchemaField({
components: {
...AllForm
},
})

export default {
components: { FormProvider, ...fields, Submit },
data() {
return {
form,
schema,
}
},
methods: {
onSubmit(value) {
console.log(value)
},
},
}
</script>

生成 Schema

上面可以看到依赖了Schema的JSON文件,这个文件可以通过设计器拖拉生成一个。

  1. 本地启动设计器

    可以引入UI库,预览效果更好,也可以支持内部的自定义组件。

  2. 使用官方线上设计器

下面是一个简单的 Schema 示例 ent-form.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
{
"form": {
"labelCol": 6,
"wrapperCol": 12
},
"schema": {
"type": "object",
"properties": {
"scu7lusqfm9": {
"type": "void",
"x-component": "FormLayout",
"x-component-props": {},
"x-designable-id": "scu7lusqfm9",
"properties": {
"name": {
"type": "string",
"title": "名称",
"x-decorator": "FormItem",
"x-component": "Input",
"x-validator": [],
"x-component-props": {},
"x-decorator-props": {},
"name": "name",
"description": "请输入名称",
"x-designable-id": "6p1ae6kj72e",
"x-index": 0
},
"type": {
"type": "string | number",
"title": "选择身份",
"x-decorator": "FormItem",
"x-component": "Radio.Group",
"enum": [
{
"children": [],
"label": "个人",
"value": 1
},
{
"children": [],
"label": "企业",
"value": 2
}
],
"x-validator": [],
"x-component-props": {},
"x-decorator-props": {},
"name": "type",
"description": "根据身份显示是否需要企业信息",
"default": 1,
"x-designable-id": "fzni7ynakt0",
"x-index": 1
},
"time": {
"type": "string",
"title": "注册时间",
"x-decorator": "FormItem",
"x-component": "TimePicker",
"x-validator": [],
"x-component-props": {},
"x-decorator-props": {},
"description": "注册时间",
"name": "time",
"x-designable-id": "61912wmibyo",
"x-index": 2
},
"ent": {
"type": "string",
"title": "企业名称",
"x-decorator": "FormItem",
"x-component": "Input",
"x-validator": [],
"x-component-props": {},
"x-decorator-props": {},
"description": "企业名称",
"name": "ent",
"x-reactions": {
"dependencies": [
{
"property": "value",
"type": "string | number",
"source": "scu7lusqfm9.type",
"name": "type"
}
],
"fulfill": {
"state": {
"hidden": "{{$deps.type !== 2}}"
}
}
},
"x-designable-id": "lwvvx5639zg",
"x-index": 3
}
},
"x-index": 0
}
},
"x-designable-id": "7wpu0smwhrw"
}
}

简单的使用及介绍就到这里,后续如果采用该方案,等使用沉淀后再总结一下。