前言
数据的双向绑定在处理表单时是一个十分有用的特性,但是React官方一直提倡的是单项数据流的思想,所以React中是并没有提供数据双向绑定的功能的,当然一般在使用React时我们还是都会使用一些组件库的,其中antd是其中比较常用的一个组件库,在这个库中就提供表单数据双向绑定的方法。
antd中form的数据双向绑定
首先我们来看一下如何使用antd中的表单组件进行数据的双向绑定:
import {
Input,
Form,
} from 'antd'
const FormItem = Form.Item;
@Form.create()
class App extends React.Component {
render() {
const { getFieldDecorator } = this.props.form;
return (
<formitem label="Note" labelcol="{{" span:="" 5="" }}="" wrappercol="{{" 12="">
{getFieldDecorator('note', {
rules: [{ required: true, message: 'Please input your note!' }],
})(
<input>
)}
</formitem>
);
}
}
首先将antd的form组件与Input组件引入进来,在使用Form时内部每一个表单元素都需要使用FormItem包裹。这些问题都不是很大,上面的代码中让人比较难以理解就是@Form.create()
,
和const { getFieldDecorator } = this.props.form;
这两行代码。
@Form.create()是什么
首先这里的@Form.create一个装饰器,它的作用就是对APP
这个类做了一层包装,并且返回了一个新的类,这个类在原始的APP
上新添加了一下功能。
其实上面的代码也可以改写成这样子:
import {
Input,
Form,
} from 'antd'
const FormItem = Form.Item
class App extends React.Component {
render() {
const { getFieldDecorator } = this.props.form;
return (
<form onsubmit="{this.handleSubmit}">
<formitem label="Note" labelcol="{{" span:="" 5="" }}="" wrappercol="{{" 12="">
{getFieldDecorator('note', {
rules: [{ required: true, message: 'Please input your note!' }],
})(
<input>
)}
</formitem>
</form>
);
}
}
const WrappedApp = Form.create()(App);
从上面的代码中能够看出Form.create
其实是一个高阶函数,这个函数执行之后返回另一个函数,然后将我们的APP
类传递给这个函数,它就会返回一个新的类。
那么返回的这个新的类有什么不同的地方吗?
从上面的代码中其实能够发现const { getFieldDecorator } = this.props.form
这一行代码是比较奇怪的。
首先我们的APP
类是基础于React.Component的,而React其实并没有提供this.props.form
的,那么我们是从哪里得到this.props.form
的呢,答案当然就是在前面执行的@Form.create()
了,前面说过执行了这个装饰器之后就相当于在原有的类上面套上了一层父类,那么这个父类自然就可以传递一些信息给子类APP
了,所以我们可以在APP
的props
中拿到form
属性。
而能够实现表单数据双向绑定的就是form提供getFieldDecorator
方法。
getFieldDecorator方法
仔细观察一下getFieldDecorator方法的用法会发现它和Form.create()(App)
其实是一样的,它也是一个高阶函数,这个函数将原本的表单组件改造了一下,使它的数据能与form
双向绑定,当表单元素数据改变时能通知到form
,也可以通过form
中的api去改变表单中的值。
自定义组件与antd的表单双向绑定
OK说了这么多那么到底如何让自定义的组件与antd的表单进行双向绑定呢?
直接将自定义组件也传到getFieldDecorator
方法中去就可以了吗?
并没有这么简单,其实如果使用过较多antd的小伙伴可能会发现,antd中Switch
组件是无法与表单进行双向绑定的,而其他的一些组件是可以的,那些能够与form进行双向绑定的组件都有一个共同的特征它们的值都是通过value
控制,值发送改变时的函数都是onChange
,而Switch
组件的值是通过checked
来控制的。
其中的原因就是经过getFieldDecorator
函数改造之后,form会通过组件的onChange
事件拿到组件内部的值,会传递一个value
的props给组件内部,一般使用value来绑定值的组件是会在组件内部监听props中的value
的变化的,当value变化时,组件内部会去改变表单组件的值。
所以自定义组件如何与antd的表单双向绑定也就很清楚了,那就是在值改变时通过onChange
方法把改变后的值传递给外部的父组件,在componentWillReceiveProps
中去监听props中的value的改变,如果value改变就改变组件的值,这样子就能够做到数据的双向绑定了。
> 作者简介:李成文,芦苇科技web前端开发工程师,擅长网站建设、公众号开发、微信小程序开发、小游戏、公众号开发,专注于前端领域框架、交互设计、图像绘制、数据分析等研究,访问 www.talkmoney.cn 了解更多。