Maison  >  Article  >  interface Web  >  Analyse détaillée du formulaire généré par JSON (exemple de code)

Analyse détaillée du formulaire généré par JSON (exemple de code)

不言
不言avant
2018-11-20 14:47:225643parcourir

Ce que cet article vous apporte est une analyse détaillée (exemple de code) du formulaire généré par JSON. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Formulaire JSON

Description

Le formulaire JSON est un composant abstrait basé sur React, qui peut convertir les formulaires décrits au format de données JSON en un formulaire dans le projet, il peut générer rapidement un formulaire Form avec seulement quelques lignes de code.
Les avantages des formulaires JSON sont :

  1. Vous pouvez rapidement créer un formulaire

  2. Les données, la logique et les vues du formulaire sont séparés pour une extraction facile. Lihe d'autres résumés

  3. Fournit des fonctions supplémentaires telles que la vérification et la mise en cache automatique pour améliorer l'expérience d'entrée

  4. Peut partager un complexe. composants de formulaire dans tous les projets

Inconvénients du formulaire d'origine

1 : Énorme quantité de code et faible efficacité de développement
Chaque fois que vous développez une page de formulaire, vous avez besoin pour écrire à plusieurs reprises les composants du formulaire et le code de ses événements interactifs est écrit à plusieurs reprises et n'a rien à voir avec la logique métier principale. De plus, des fonctions supplémentaires telles que la vérification du formulaire et la mise en cache nécessitent également beaucoup de code, ce qui entraîne un problème. formulaire page de code.

2 : Il n'est pas facile de séparer et d'abstraire davantage
Dans une page de formulaire, les données du formulaire, les composants du formulaire et la logique de contrôle sont souvent mélangés lorsqu'il s'avère qu'une certaine sous-fonction est. utilisé dans de nombreux scénarios Lorsqu'ils doivent tous être utilisés, il n'est pas facile de séparer la sous-fonction. Étant donné que la logique, les données et les vues sont mélangées, il faut une inspection minutieuse pour supprimer la sous-fonction sans être affectée, ce qui est nécessaire. conduit à l'échec de la fonction. L'inconvénient de la séparation et de l'abstraction

3 : Coût de maintenance élevé
C'est la même raison que le deuxième problème. C'est aussi mon expérience personnelle Quand je veux optimiser. une petite fonction dans le projet A cette époque, j'ai constaté que non seulement la logique précédente avait été modifiée, mais aussi que de nombreux bugs étaient introduits, ce qui faisait de la maintenance une tâche à haut risque sous une forme avec une logique très complexe.

4 : Un traitement supplémentaire de fonctions telles que la vérification et la mise en cache est requis

Une châtaigne

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>

Ce qui précède est un formulaire composé de trois composants de formulaire couramment utilisés décrits dans JSON , le rendu est le suivant :

Analyse détaillée du formulaire généré par JSON (exemple de code)

Format du formulaire JSON

{
    formKey: 'paramAddForm',
    data: {},
    config: []
}
属性 是否必传 说明 类型 默认值
formKey 用来自动缓存,localStorage的key,不传表示不自动缓存 string -
className 用来添加一些自定义样式 string -
data 表单的提交数据,有自动缓存和校验功能 object -
assisData 用于表单控制逻辑的额外数据 object -
config 组件配置,表单组件的配置 Array -
realTimeSubmit 表单是否实时提交,一般用于筛选表单 boolean false

表单组件的配置

{
    type: 'input',
    dataKey: 'name',
    label: 'param',
    validate: ['required'],
    style: {}
}
属性 是否必传 说明 类型 默认值
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 -

关键字段解释

1. type

type是用来唯一表示表单组件类型的字段,其中JSON表单提供了三种默认的表单组件:input、select、textarea,还有两种复杂类型的表单组件:form_array、container。

form_array表单组件表示其数据结构为Array,含有增加项删除项的复合表单组件,该表单组件的配置里多一个children的字段,里面是每一项里面的表单组件配置的集合,其表单组件的效果如下图所示:

Analyse détaillée du formulaire généré par JSON (exemple de code)

container是用来自定义表单的接口,具体用法参考下面具体的介绍。

2. validate

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) => {}]

3. style

用来确定表单组件在表单内的布局样式,比如想让表单组件行内显示,且宽度为200,其style值如下:

{
    display: 'inline-block',
    width: 200
}

container表单组件

container表单组件是用来自定义表单组件的,它主要的作用有以下几点:

  1. 添加表单组件库,例如Ant-Design

  2. 自定义表单组件,例如图片上传组件

  3. 用来构建复杂的表单组件

  4. 处理控制逻辑和联动逻辑

使用栗子

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中依然可以嵌套表单组件。

使用antd的组件库

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数据。

render方法内嵌套组件配置

{
    type: 'container',
    dataKey: 'param',
    render: (curData, config, {changeFn, changeDataFn, JSONForm}) => {
        return <p>
            {
                JSONForm([
                    {
                        type: 'input',
                        dataKey: 'name',
                        placeholder: '请输入param',
                        validate: ['required'],
                    }
                ])
            }
        </p>
    }

这样就可以在container内嵌套组件配置,实现更复杂的表单组件。

JSON表单提交数据

非实时表单提交

非实时表单提交数据,就是在表单输入完毕后,点击提交按钮统一提交所有的数据,其提交的方式如下:

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
}

JSON表单的应用场景

表单分类

a. 按复杂度分类
   1. 简单表单:表单组件为input、select、textarea等常见的几种,且表单组件之间逻辑独立
   2. 复杂表单:表单组件内容和交互复杂且相互之间存在复杂的逻辑
其中复杂表单又可以分为:
   1. 联动表单,上一个表单组件会影响接下来表单的值
   2. 实时表单,表单组件的事件会触发表单的实时提交,例如筛选表单
   3. 富控制表单,表单内部含有很多的控制逻辑

JSON表单最适合的应用场景是简单表单,它可以用极少的代码,快速的构建出表单来,对于复杂类型的表单,JSON表单需要使用container来构建复杂的表单组件、处理复杂的控制逻辑,其代码量优势虽然并不明显,但是JSON表单可以使其代码清晰,将表单组件和表单逻辑彻底解耦,便于抽离和维护,便于共享常用组件,也带来不少的好处。

到目前为止,JSON表单适合大部分的表单应用场景。

JSON表单解决的问题

  1. 减少了表单代码量,不需要重复的开发表单组件,只需要输入组件配置即可

  2. 将表单组件和数据解耦,便于子功能的拆分和常用组件的共享

  3. 简化了校验功能,只需要传入validate字段即可

  4. 添加了自动缓存功能

在我的项目,我尝试了使用原始表单和JSON表单两种方式来实现同一个表单页,原始表单我编写了600多行的代码,而在JSON表单中,只有不到150行。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer