Antd Form

4,146 阅读2分钟

应用react的时候总是会绕不过antd,并且在最近做的项目中,大量使用了表单,表格嵌表单这种复杂的数据交互,多多少少采了些坑,下定决心把收获和踩得坑总结一下。

引入表单方法

首先想要应用表单中的一系列方法,要调用Form的create方法,这样组件的props里面就会包含一个form属性,它包含了一系列的方法。

表单使用

<Form>
    <Form.Item  label="标签名称" >
        {getFieldDecorator(' name[0].name1', {
            rules: [{ required: true, message: '不可为空' }],
            initialValue: _.get(name,'[0].name1'),
        })(
            <Select>
                {options.map(item => (
                   <Option value={item.id}>{item.name}</Option>
                ))}
           </Select>,
        )}
    </Form.Item>
</Form>
  • 属性label 是表单前面显示的标签,可以通过添加colon、labelCol、 wrapperCol、labelAlign 这些属性来调整label的样式。

数据双向绑定

通过受控组件的onChange方法,就达到数据双向绑定,但是在表单中涉及到大量的数据交互,过多的onChange方法显得有些繁琐,所以应用form表单的getFieldDecorator方法,可以方便的实现一系列的规则验证和数据绑定。

应用双向绑定后的表单,会维护一个数据树,数据同步将被 Form 接管,抛弃onChange方法,defaultValue换成initialValuesetStatethis.props.form.setFieldsValue代替。

getFieldDecorator(id:String, options:Object)=>(React.Node)=>React.Node
  • id代表数据的唯一标志,可以通过变量拼接的方法达到嵌套目的,例如:
getFieldDecorator('name[0].name1') 

这样在我们获取表单数据的时候,数据格式会是 name:[name1:value]这种形式。方便和我们自己的数据结构做统一。注意id 需要传递变量的时候尽量用字符串模板:

`name[${index}].name1`
  • options包含一系列验证规则和控制表单项属性:
    1. options.rules:object[] 表单验证规则。数组内每个对象可以定义一个验证规则,如上述代码中{ required: true, message: '不可为空' }required 表示是否必填项,message 代表发生验证错误时的提示信息。

    2. options.initialValue:any 表单项初始化值,适当的定义id 的结构,使它和初始化的数据对应起来就可以方便应用数据。但是需要注意的是,form中的所有初始化值都是在第一次渲染的时候起作用,一旦相应表单被修改,那么initialValue就不起作用了,表单校验使用的是浅比较,所以初始化值最好引用变量,尽量不要直接用对象。

    3. Options.normalize:function(value, prevValue, allValues): any 实时转换表单值,可以用函数返回值转换相应表单项值,但是值得注意的是,应用中发现,每次表单中的任一项有更新,这个normalize函数都会执行,所以要做好空数据兼容和性能考虑。

    比较有意思的是,如果应用normalize的表单项是moment类型数据,一旦应用normalize设置了相应的值的时分秒,那么后续再选择日历得到的默认时分秒都是上次设置的值,不再获取当前时分秒。

    1. Options.validateFirst:boolean布尔值,当为true的时候,那么验证表单时,一旦发生错误就不继续向下验证了,可以在大量表单验证的时候提高性能。默认值false。

列举了几个比较常用的属性,此外options还有许多其他属性,可以移步官方文档: antd表单

交互组件

getFieldDecorator方法返回一个函数,接收一个交互组件作为参数,执行完统一返回React.Node类型组件。这样,form就为组件完成了数据双向绑定。并且提供了一系列的内置校验及警告功能。

在使用getFieldDecorator方法的时候,antd并不提倡我们在一个item内部写多个getFieldDecorator方法,这样会让我们的双向绑定中的验证方法失效。

假如涉及到一个数组类型的数据,每条包含一个id,并且id不能展示,但是提交的时候又必须上传,那么在表单中绑定处理器数据来就比较简单:

 <Item>
    {getFieldDecorator(`dataList[${index}].list[${i}].id`, { initialValue: record.id })(<span></span>)}
</Item>

上述id并没有展示,但是最后获取表单数据的时候是存在表单数据树中的,算是投机取巧了。

获取/设置表单数据

getFieldsValue([fieldNames: string[]])
setFieldsValue({
  [fieldName]: {value: any, errors: [Error] }
})

getFieldsValue不传任何参数,获取的是所有表单数据;setFieldsValue方法其实是应用了setState机制,所以使用的时候需要注意。

提交验证

Form在提交表单的时候,会涉及到统一的验证。

form.validateFields(
    [fieldNames: string[]],
    [options: object],
    (errs:{name: string,value: any},vals) => {
        if(errs){
            return;
        }
        // todo
    }
)

如果fieldNames参数不传,则校验所有的项;options参数涉及到一系列校验规则设置。回调函数接收校验error和表单value作为参数。errs是fieldName和errValue组成的对象;vals是表单维护的数据树。

重置表单

resetFields()

该方法将表单重置成最初的数据结构,此时表单并不是全部置空,如果表单项中有initialValue的话,那么表单会重置成initialValue