亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

JSON生成Form表單的方法示例

2019-11-19 12:29:32
字體:
來源:轉載
供稿:網友

JSON表單描述

JSON表單是一個基于React的抽象組件,它可以把JSON數據格式描述的表單轉換成項目中的表單,它可以用簡短的幾行代碼,快速的生成Form表單。

JSON表單的優點是:

  • 可以快速構建出一個表單
  • 表單的數據、邏輯、視圖分離,方便抽離和進一步抽象
  • 提供校驗、自動緩存等額外功能,提升錄入體驗
  • 可以跨項目的共用復雜的表單組件

原始表單的缺點

1:代碼量龐大,開發效率低
每次開發一個表單頁的時候,都需要重復編寫表單組件及其交互事件的代碼,這塊代碼重復編寫且與主線業務邏輯無關,除此之外,表單的校驗、緩存等額外功能,也需要不少的代碼量,這樣就造成了一個表單頁的代碼量龐大。

2:不便于抽離和進一步的抽象
在一個表單頁內,往往會將表單數據、表單組件、控制邏輯雜糅在一起,當發現某一個子功能在很多場景下都需要用到的時候,想把該子功能拆分出來發現并不容易,因為邏輯、數據、視圖的雜糅,導致想把子功能不受影響的剔除出來需要很仔細的檢查,這樣就導致功能的抽離和抽象的不便

3:維護成本高
這個和第二個問題是同樣的原因,這也是我的親身經歷,當我在項目中想優化一個小功能的時候,發現不僅把之前的邏輯改沒了,還引出了不少的bug,這導致在一個邏輯很復雜的表單里,維護變成了一件高危工作。

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 ref={ref => this.FormWrap = ref} config={config}></From>

上面是用JSON描述的三個常用的表單組件組合成的表單,其效果圖如下:

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的字段,里面是每一項里面的表單組件配置的集合,其表單組件的效果如下圖所示:

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表單組件是用來自定義表單組件的,它主要的作用有以下幾點:

  • 添加表單組件庫,例如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 value={curData}       style={{width: '100%', height: 35}}       onMouseEnter={getFocus}      onChange={(value) => changeFn(value, () => {        loseFocus()      })}>      {        config.options && config.options.map((item, idx) => <Option key={idx} value={item}>{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 value={curData}         onFocus={getFocus}        onBlur={loseFocus}        placeholder={config.placeholder ? config.placeholder : ''}        style={{borderColor: !!error ? '#f5222d' : ''}}        onChange={event => 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 ref={ref => 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 placement="top" content="刷新param列表">              <Button shape="circle" loading={curData} onClick={handleClick}>{!curData && <Icon type="reload" />}</Button>            </Popover>          }        </React.Fragment>      }    },  ]}

注意: 如果要使用assistData中的數據,其dataKey必須以assistData開頭,且必須使用changeDataFn自定義提交assistData數據。

render方法內嵌套組件配置

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

這樣就可以在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表單解決的問題

  • 減少了表單代碼量,不需要重復的開發表單組件,只需要輸入組件配置即可
  • 將表單組件和數據解耦,便于子功能的拆分和常用組件的共享
  • 簡化了校驗功能,只需要傳入validate字段即可
  • 添加了自動緩存功能

在我的項目,我嘗試了使用原始表單和JSON表單兩種方式來實現同一個表單頁,原始表單我編寫了600多行的代碼,而在JSON表單中,只有不到150行。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产男人精品视频| 国产99久久精品一区二区 夜夜躁日日躁| 亚洲一区二区三区乱码aⅴ| 一区二区福利视频| 久久九九国产精品怡红院| 欧美日韩亚洲系列| 久久亚洲国产成人| 亚洲国产精品va在看黑人| 国产精品久久久久久久午夜| 97在线观看免费高清| 国模精品一区二区三区色天香| 日韩av在线免费观看一区| 538国产精品一区二区在线| 国产精品精品久久久| 亚洲国产成人久久综合一区| 亚洲男人天堂九九视频| 久久久久国产精品免费网站| 萌白酱国产一区二区| 午夜美女久久久久爽久久| 欧美成人免费va影院高清| 精品视频久久久久久久| 日韩电影中文字幕在线观看| 欧美激情视频免费观看| 久久久久国色av免费观看性色| 日韩成人久久久| 国产成人精品综合久久久| 福利二区91精品bt7086| 91爱视频在线| 欧美美女15p| 成人黄色短视频在线观看| 亚洲自拍av在线| 欧美午夜电影在线| 国产免费一区二区三区在线观看| 精品国产区一区二区三区在线观看| 精品久久久久久亚洲精品| 久久午夜a级毛片| 91香蕉嫩草影院入口| 国产精品毛片a∨一区二区三区|国| 日韩在线视频国产| 国产a级全部精品| 国产精品香蕉在线观看| 欧美高清一级大片| 日韩精品视频在线观看免费| 亚洲国产精品免费| 日韩在线欧美在线国产在线| 91av成人在线| 国产精品成熟老女人| 久久噜噜噜精品国产亚洲综合| 免费av一区二区| 国产一区二中文字幕在线看| 欧美极品美女视频网站在线观看免费| 亚洲一区二区免费| 久久久久久久久久国产| 亚洲bt欧美bt日本bt| 国产美女久久精品香蕉69| 九九热精品视频| 97久久精品国产| 日韩成人久久久| 68精品久久久久久欧美| 久久全国免费视频| 欧美一级成年大片在线观看| 日韩欧美在线视频日韩欧美在线视频| 97在线看免费观看视频在线观看| 欧美成人自拍视频| 91精品91久久久久久| 中文字幕久精品免费视频| 中文字幕在线日韩| 国产精品免费在线免费| 在线播放精品一区二区三区| 91av在线不卡| 最近2019年中文视频免费在线观看| 91欧美精品成人综合在线观看| 日韩av成人在线观看| 久久久精品视频在线观看| 成人在线精品视频| 98视频在线噜噜噜国产| 国产成人小视频在线观看| 91久久国产综合久久91精品网站| 国产精品亚洲精品| 91欧美日韩一区| 国产精品一区二区三区在线播放| 97成人精品视频在线观看| 国产欧美一区二区白浆黑人| 国产精品视频久久| 国产精品高潮呻吟视频| 欧美日韩亚洲一区二区三区| 亚洲精品视频在线观看视频| 亚洲欧美国产一本综合首页| 日韩色av导航| 成人精品福利视频| 国产91精品青草社区| 91热精品视频| 久久久精品免费| 国产精品扒开腿做爽爽爽男男| 国产精品激情av电影在线观看| 91国自产精品中文字幕亚洲| 国产亚洲激情在线| 欧美激情视频一区二区三区不卡| 日韩欧美精品网站| 国产一区二中文字幕在线看| 日韩电视剧免费观看网站| 91久久在线播放| 亚洲精品videossex少妇| 亚洲女人被黑人巨大进入al| 91av视频导航| 日本精品视频网站| 久久久爽爽爽美女图片| 国外成人在线播放| 国产精品一二三在线| 亚洲风情亚aⅴ在线发布| 久久精品影视伊人网| 97婷婷涩涩精品一区| 亚洲国产天堂久久综合| 91九色在线视频| 2019中文在线观看| 亚洲人成绝费网站色www| 成人网在线视频| 国产欧美一区二区三区久久人妖| 日韩免费电影在线观看| 亚洲成人xxx| 国产欧美日韩最新| 日韩在线视频网站| 久久99精品国产99久久6尤物| 九九热精品在线| 亚洲精品福利在线观看| 亚洲精品美女久久| 久久久久久久久久久免费精品| 久久久人成影片一区二区三区观看| 久久久亚洲天堂| 亚洲人成77777在线观看网| 深夜福利91大全| 欧美片一区二区三区| 亚洲精品aⅴ中文字幕乱码| 国产成人涩涩涩视频在线观看| 欧洲成人性视频| 亚洲国产欧美一区二区丝袜黑人| 欧美日韩国产丝袜美女| 亚洲第一中文字幕| 成人女保姆的销魂服务| 4p变态网欧美系列| 欧美性猛交xxxx乱大交3| 亚洲国产天堂网精品网站| 成人免费淫片aa视频免费| 欧洲日韩成人av| 136fldh精品导航福利| 欧美日韩国产中文精品字幕自在自线| 国产精品99久久久久久久久久久久| 97国产成人精品视频| 亚洲精品理论电影| 亚洲精品720p| 成人亚洲综合色就1024| 日韩视频在线免费| 日本久久中文字幕| 日韩精品在线播放| yw.139尤物在线精品视频| 亚洲国产美女精品久久久久∴| 国产成人精品在线视频| 亚洲人精品午夜在线观看| 日韩欧美aⅴ综合网站发布| 国产精品视频在线观看| 91精品国产91久久久久久不卡| 久久精品国产亚洲7777| 欧美性xxxx极品高清hd直播| 亚洲综合第一页|