在开发过程中,表单组件是非常常用的组件之一。在antd中,个人倾向于使用getFieldDecorator
去创建formItem
。默认的input/select
等组件有时候不太能满足需求,所以就会需要自定义一些组件,传递给getFieldDecorator
。
一个简单的例子
假设我们需要封装一个可以过滤远程数据的组件,即antd
的select
组件的search
功能。这个组件会根据输入去特定接口获取数据,然后显示出来,供用户筛选。组件封装如下
基本实现
// 务必使用class方式,如果使用function形式的话,无法被getFieldDecorator使用
class ExampleSeach extends React.Component {
constructor(props) {
super(props)
this.state = {
value: '',
options: []
}
}
handleSearch = async (value) => {
if (value) {
// 加载远程数据
let res = await fetchData()
this.setState({
options: res
})
} else {
this.setState({
options: []
})
}
}
handleChange = value => {
this.setState({
value: value
})
// 下面一行代码是关键,在被getFieldDecorator包装后,会绑定一个onChange事件,
// 接收的第一个参数将作为当前formItem的value
this.props.onChange(value)
}
render() {
const opts = options.map(ele => <Option key={ele.value}>{ele.label}</Option>)
return (
<Select
showSearch
value={this.state.value}
defaultActiveFirstOption={false}
showArrow={false}
filterOption={false}
onSearch={this.handleSearch}
onChange={this.handleChange}
notFoundContent={null}
>
{opts}
</Select>
)
}
}
以上就实现了一个自定义的远程过滤组件的封装,可以像用Input等组件一样直接在getFieldDecorator
中使用了。
进阶需求
如果想给该组件手动赋值(比如编辑某个数据的时候,表单元素默认已经有值了)
// 1. 组件中添加生命周期
static getDerivedStateFromProps(nextProps, prevState) {
// 经过getFieldDecorator封装以后,props会有value属性,代表外部传递过来的值
if (nextProps.value !== prevState.value) {
return {
value: nextProps.value
}
}
return null
}
// 2. getFieldDecorator中使用的是,通过initialValue赋值
// 或者在表单创建完成后,使用setFields去给表单赋值,这样都会触发自定义组件的生命周期,从而改变组件的值
总结
自定义一个表单元素组件,关键就是在组件中的数据变化的时候,去调用props.onChange事件,将组件的值传递到外面