この記事では、JSON で生成された Form フォームの詳細な分析 (コード例) を紹介します。必要な方は参考にしていただければ幸いです。
JSON フォーム
説明
JSON フォームは React をベースにした抽象コンポーネントで、JSON データ形式で記述されたフォームを次の形式に変換できます。プロジェクト内のフォームを使用すると、わずか数行のコードでフォーム フォームをすばやく生成できます。
JSON フォームの利点は次のとおりです。
フォームを迅速に構築できます
JSON フォームのデータ、ロジック、ビュー簡単に抽出できるようにフォームが分離されています さらに詳しい要約
入力エクスペリエンスを向上させるための検証や自動キャッシュなどの追加機能を提供します
複雑な内容を共有できますプロジェクト間でのフォーム コンポーネント
1: 膨大な量のコードと低い開発効率
フォーム ページを開発するたびに、フォーム コンポーネントとそのインタラクティブ イベントのコードは繰り返し記述され、主要なビジネス ロジックとは何の関係もありません。さらに、フォームの検証やキャッシュなどの追加機能にも大量のコードが必要になるため、膨大な量のコードのフォームページ。
2: 抽象化し、さらに抽象化するのは簡単ではありません。
フォーム ページでは、特定のサブ機能が判明した場合、フォーム データ、フォーム コンポーネント、および制御ロジックが混在していることがよくあります。多くのシナリオで使用されます。すべてを使用する必要がある場合、ロジック、データ、ビューが混在しているため、サブ関数を分離するのは簡単ではありません。そのため、影響を受けずにサブ関数を削除するには慎重な検査が必要です。分離と抽象化の不便さ
3: メンテナンスコストの高さ
これは 2 番目の問題と同じ理由で、小さな関数を最適化したい場合にも当てはまります。その際、以前のロジックが変更されているだけでなく、多くのバグが導入されており、非常に複雑なロジックを持つ形式でのメンテナンスはリスクの高い作業であることがわかりました。
4: 検証やキャッシュなどの機能の追加処理が必要です
const config = { formKey: 'example-form', data: { name: '', descr: '', typeName: '' }, config: [ { type: 'input', dataKey: 'name', label: 'param', placeholder: '请输入param', validate: ['required', /^[a-zA-Z_{}0-9]+$/g], style: { display: 'inline-block', width: 270, }, }, { type: 'select', dataKey: 'typeName', options: ['string', 'integer', 'float'], style: { display: 'inline-block', width: 100, margin: '0 15px' }, validate: [{type: 'required', message: 'param类型不能为空'}] }, { type: 'textarea', dataKey: 'descr', placeholder: '请输入param含义', label: 'param含义', validate: ['required'], style: { width: 385, } }, ] } <from> this.FormWrap = ref} config={config}></from>
上記は、JSON で記述されたよく使用される 3 つのフォームコンポーネントで構成されるフォームです。レンダリングは次のとおりです。
{ formKey: 'paramAddForm', data: {}, config: [] }
Attributes | 必須かどうか | 説明 | タイプ | デフォルト値 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
formKey | No | 自動キャッシュに使用されます。localStorage キー。渡されない場合は、自動キャッシュがないことを意味します。 | string | - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
No | カスタム スタイルを追加するために使用されます | string | - | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
は、自動キャッシュおよび検証機能を備えた | フォームの送信データです | object | - | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
No | フォーム コントロール ロジック用の追加データ | object | - | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
は | コンポーネント構成、フォームコンポーネント | Array | - | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
フォームがリアルタイムで送信されるかどうか。通常はフォームをフィルターするために使用されます。 | boolean | false |
属性 | 是否必传 | 说明 | 类型 | 默认值 |
---|---|---|---|---|
type | 是 | 表单组件的类型,其值可以为: input、select、textarea、form_array、container和一些自定义表单组件 | string | - |
dataKey | 否 | 指定表单组件值的key,可以为param.name.firstName形式 | string | - |
label | 否 | 表单组件的label | string | - |
placeholder | 否 | 表单组件的placeholder | string | - |
validate | 否 | 表单组件的校验规则 | Array | - |
style | 否 | 表单组件的布局样式 | string | - |
options | 否 | 当表单组件为select时,需要传入的options | Array | - |
render | 否 | 当type为container时,为自定义组件,render为渲染方法 | Function | - |
preventSubmit | 否 | 当realTimeSubmit为true时,控制当前表单组件是否实时提交 | boolean | false |
children | 否 | 当type为form_array时,children表示子组件配置列表 | Array | - |
modifyDataFn | 否 | 当type为自定义组件时,且需要覆盖render方法中的提交数据方法,可以使用modifyDataFn来重新自定义提交数据 | Function | - |
type是用来唯一表示表单组件类型的字段,其中JSON表单提供了三种默认的表单组件:input、select、textarea,还有两种复杂类型的表单组件:form_array、container。
form_array表单组件表示其数据结构为Array,含有增加项删除项的复合表单组件,该表单组件的配置里多一个children的字段,里面是每一项里面的表单组件配置的集合,其表单组件的效果如下图所示:
container是用来自定义表单的接口,具体用法参考下面具体的介绍。
validate是校验表单组件数据正确性的字段,其值为数组,里面的数组元素可以为String、object、RegExp、Function。
JSON表单采用的是async-validator
异步处理校验,在JSON表单内部会将validate传入的校验关键字解析为async-validator
的rules。所以validate数组元素如果为object的话,其内容就是async-validator
的rules。
1. 数组元素为string,其值可以为: string,值必须为string number,值必须为数字 required,值不能为空 boolean,值必须为布尔值 integer,值必须为整数形 float,值必须为浮点型 email,值必须为邮箱类型 2. 数组元素为object,其值为rules: {type: 'enum', enum: ['1', '2'], message: '值不在确定范围内'} 3. 数组元素为RegExp, validate: [/^[a-zA-Z_{}0-9]+$/g] 4. 数组元素为Function, validate: [ (rules, value, callback) => {}]
用来确定表单组件在表单内的布局样式,比如想让表单组件行内显示,且宽度为200,其style值如下:
{ display: 'inline-block', width: 200 }
container表单组件是用来自定义表单组件的,它主要的作用有以下几点:
添加表单组件库,例如Ant-Design
自定义表单组件,例如图片上传组件
用来构建复杂的表单组件
处理控制逻辑和联动逻辑
import { Input, Select } from 'antd' const Option = Select.Option { type: 'container', dataKey: 'descr', style: { display: 'inline-block', width: 100, margin: '0 15px' }, options: ['string', 'integer', 'float'], render: (curData, config, {changeFn, getFocus, loseFocus, error}) => { return <select> changeFn(value, () => { loseFocus() })}> { config.options && config.options.map((item, idx) => <option>{item}</option>) } </select> } },
container表单组件只是多一个render渲染方法,里面可以自定义表单组件的渲染内容,render方法提供如下参数:
1. curData: 当前container组件的值,跟dataKey相关
2. config: 当前container组件的配置
3:{changeFn, changeDataFn, getFocus, loseFocus, error, JSONForm}
changeFn, changDataFn是提交数据的方法,changeFn只能修改当前组件dataKey的值,changeDataFn可以修改data中任意字段的值,changeFn(value, [callback]), changeFn(dataKey, value, [callback])
getFocus,loseFocus是自定义处理校验的字段,loseFocus是开始校验,getFocus是去掉校验的报错信息
error是校验结果的报错信息
JSONForm是在container中使用JSON表单的组件配置用来生成新的表单组件,意思里container中依然可以嵌套表单组件。
JOSN表单只提供了input、select、textarea三种默认的表单组件,远远不够真实的项目中使用,所以我们可以将antd组件库中的组件封装到JSON表单中,这样我们就可以再项目中很快的使用antd中的组件。
antd-components.js
import React from 'react' import { Input } from 'antd' export default [ { type: 'antd-input', render: (curData, config, {changeFn, getFocus, loseFocus, error}) => { return <input> changeFn(event.target.value)} /> } } ]
我们在antd-components.js文件中声明一个antd-input
的自定义组件,然后在JSON表单中引入该自定义表单组件:
init.js
import Form from 'Form' import components from './antd-components' From.createCustomComp(components) const config = { formKey: 'paramAddFromAntd', data: { name: '', }, config: [ { type: 'antd-input', dataKey: 'name', label: 'Param', placeholder: '请输入param', validate: ['required', /^[a-zA-Z_{}0-9]+$/g] } ] } <from> this.FormWrap = ref} config={config}></from>
使用container来引入antd组件库,其原理就是通过container将antd组件封装成'antd-input'自定义组件,然后使用它,这种方式不仅可以用来封装组件库,还可以用来共享一些共用表单组件,可以将常用的复杂表单组件封装在一个共用文件里,然后在不同项目中引用,就可以跨项目共用表单组件。
在自定义组件中,如果需要自定义表单提交数据函数,但是又不能重写render方法以防覆盖原先的render方法,所以可以使用modifyDataFn方法来覆盖render中的提交数据部分。
modifyDataFn: ({changeFn, changeDataFn}, {parent, self}) => { let {parentData} = parent parentData = parentData.map(item => ({ ...item, name: self.curData })) changeDataFn(parent.parentKey, parentData) }
在JSON表单JSON配置中,有assistData的选填字段,该字段为JSON表单处理控制逻辑的额外数据,例如在表单内有一个刷新按钮,其实现代码如下:
{ data: {}, assistData: { refreshParam: false }, config: [ { type: 'container', dataKey: 'assistData.refreshParam', render: (curData, config, {changeFn, changeDataFn}) => { const handleClick = () => { changeDataFn('assistData.refreshParam' ,true) setTimeout(() => { changeDataFn('assistData.refreshParam' ,false) }, 1000 * 3) } return <react.fragment> { config.index === config.parentData.length - 1 && <popover> <button>{!curData && <icon></icon>}</button> </popover> } </react.fragment> } }, ] }
注意: 如果要使用assistData中的数据,其dataKey必须以assistData
开头,且必须使用changeDataFn
自定义提交assistData数据。
{ type: 'container', dataKey: 'param', render: (curData, config, {changeFn, changeDataFn, JSONForm}) => { return <p> { JSONForm([ { type: 'input', dataKey: 'name', placeholder: '请输入param', validate: ['required'], } ]) } </p> }
这样就可以在container内嵌套组件配置,实现更复杂的表单组件。
非实时表单提交数据,就是在表单输入完毕后,点击提交按钮统一提交所有的数据,其提交的方式如下:
function handleClick() { this.FormRefs.getValue((valid, data) => { // valid 表示校验结果,false表示校验不通过 }) }
实时表单的提交首先需要注册提交函数:
componentDidMount(){ this.FormRefs.registerSubmit((valid, data) => { console.log(valid, data) }) }
接着在配置里设置允许实时提交的字段:
{ formKey: '', realTimeSubmit: true }
如果需要在某些表单组件里自定义是否实时提交,需要在组件配置里设置阻止实时提交字段为true:
{ dataKey: '', preventSubmit: true }
a. 按复杂度分类
1. 简单表单:表单组件为input、select、textarea等常见的几种,且表单组件之间逻辑独立
2. 复杂表单:表单组件内容和交互复杂且相互之间存在复杂的逻辑
其中复杂表单又可以分为:
1. 联动表单,上一个表单组件会影响接下来表单的值
2. 实时表单,表单组件的事件会触发表单的实时提交,例如筛选表单
3. 富控制表单,表单内部含有很多的控制逻辑
JSON表单最适合的应用场景是简单表单,它可以用极少的代码,快速的构建出表单来,对于复杂类型的表单,JSON表单需要使用container来构建复杂的表单组件、处理复杂的控制逻辑,其代码量优势虽然并不明显,但是JSON表单可以使其代码清晰,将表单组件和表单逻辑彻底解耦,便于抽离和维护,便于共享常用组件,也带来不少的好处。
到目前为止,JSON表单适合大部分的表单应用场景。
减少了表单代码量,不需要重复的开发表单组件,只需要输入组件配置即可
将表单组件和数据解耦,便于子功能的拆分和常用组件的共享
简化了校验功能,只需要传入validate字段即可
添加了自动缓存功能
在我的项目,我尝试了使用原始表单和JSON表单两种方式来实现同一个表单页,原始表单我编写了600多行的代码,而在JSON表单中,只有不到150行。
以上がJSON生成フォームの詳細分析(コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。