實現Ant Design 自定義表單組件


  Ant Design 組件提供了InputInputNumberRadioSelectuplod等表單組件,但實際開發中這是不能滿足需求,同時我們希望可以繼續使用Form提供的驗證和提示等方法(使用起來確實很爽),這時需要自己動手封裝一些表單,同時我們還要保持方法可以繼續是使用。

  github的代碼地址: https://github.com/haozhaohang/ant-design-expand-component

 

  下面看一下如何自己封裝表單組件,這是一個最基礎的表單使用例子:

 1 import React, { PureComponent } from 'react'
 2 import { Button, Form, Input, Radio } from 'antd'
 3 import FormItem from 'components/FormItem'
 4 
 5 const RadioGroup = Radio.Group
 6 const options = [
 7     { label: '男', value: 1 },
 8     { label: '女', value: 2 },
 9 ]
10 
11 class Test extends PureComponent {
12     handleSubmit = (e) => {
13         e.preventDefault();
14 
15         const { form: { validateFields } } = this.props;
16 
17         validateFields((errors, values) => {
18             if (errors) {
19                 return;
20             }
21             console.log(values)
22         })
23     }
24 
25     render() {
26         const { form: { getFieldDecorator } } = this.props
27 
28         const nameDecorator = getFieldDecorator('name')
29         const sexDecorator = getFieldDecorator('sex')
30 
31         return (
32             <section>
33                 <Form layout="horizontal" onSubmit={this.handleSubmit}>
34                     <FormItem label="姓名">
35                         {nameDecorator(<Input />)}
36                     </FormItem>
37 
38                     <FormItem label="年齡">
39                         {sexDecorator(<RadioGroup options={options} />)}
40                     </FormItem>
41 
42                     <FormItem buttonsContainer>
43                         <Button type="primary" size="default" htmlType="submit">提交</Button>
44                     </FormItem>
45                 </Form>
46             </section>
47         );
48     }
49 }
50 
51 export default Form.create()(Test)

 

  現在需求需要我們實現多個姓名的提交,這時使用UI組件提供的表單便無法實現。

  下面我們可以封裝一個InputArrary組件:

 1 import React, { PureComponent } from 'react'
 2 import PropTypes from 'prop-types'
 3 import { Button, Icon, Input } from 'antd'
 4 
 5 import './index.scss'
 6 
 7 class InputArray extends PureComponent {
 8     constructor(props) {
 9         super(props)
10     }
11 
12     handleChange = index => {
13         const { value, onChange } = this.props
14         const newValue = [...value]
15 
16         newValue[index] = target.value
17 
18         onChange(newValue)
19     }
20 
21     handleDelete = e => {
22         const target = e.currentTarget
23         const index = target.parentNode.parentNode.firstChild.dataset.index
24         const { value, onChange } = this.props
25         const newValue = [...value]
26 
27         newValue.splice(Number(index), 1)
28 
29         onChange(newValue)
30     }
31 
32     handleAdd = () => {
33         const { value, onChange } = this.props
34         const newValue = [...value, '']
35 
36         onChange(newValue)
37     }
38 
39     render() {
40         const { value, ...others } = this.props
41 
42         const closeBtn = <Icon type="close-circle" onClick={this.handleDelete} />
43 
44         return (
45             <div className="input-array-component">
46                 {value.map((v, i) => {
47                     return (
48                         <div key={i}>
49                             <Input
50                                 {...others}
51                                 value={v}
52                                 suffix={closeBtn}
53                                 data-index={i}
54                                 onChange={() => this.handleChange(i)}
55                             />
56                         </div>
57                     );
58                 })}
59                 <div>
60                     <Button type="dashed" icon="plus" onClick={this.handleAdd}>添加</Button>
61                 </div>
62             </div>
63         );
64     }
65 }
66 
67 InputArray.defaultProps = {
68     value: []
69 }
70 
71 export default InputArray

   

  這是我們就可以像引入Input組件一樣引入InputArray組件實現了一組姓名的提交。

<FormItem label="姓名">
        {nameDecorator(<InputArray />)}
</FormItem

  組件主要使用的form提供getFieldDecorator方法,這個方法會向組件注入value參數,onChange方法,每次調用onChange方法都會去改變value,從而刷新整個組件。為什么會這樣那,其實Ant Design 會在表單組件外層包裹一層組件,維護一個State值,每次onChange都是在改變外部state值,調用setState來刷新表單組件。

  

  Upload組件使用中也遇到一個坑,Upload組件action上傳地址參數也是必填參數,每次上傳都會直接上傳到服務器,不能和其它表單的數據一起提交,這時候我們也必須從新封裝一個上傳組件,同時因為存在文件或圖片數據就不能使用json格式和后台進行交互,必須使用new FormData()的數據格式上傳,也就是原生的表單的submit提交。

 

  特別注意:

    編寫自定義組件時,使用getFieldDecorator過程中,會遇到 (Warning: getFieldDecorator will override value, so please don't set value directly and use setFieldsValue to set it.  )這樣的警告,這是因為我們在自定義組件中定義了value值,getFieldDecorator會覆蓋我們定義的值,需要添加默認值可以使用在getFieldDecorator的時候,設置initialValue,刪除在自定義組件中定義的value就可以了!可以查看issue#1

 

  github的代碼地址: https://github.com/haozhaohang/ant-design-expand-component

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM