antd form | react-final-form | redux-form | |
---|---|---|---|
customize Field | yes | yes | yes |
asyncValidating | yes | yes | yes |
form create | HOC | Context | Context, HOC |
react 16 | yes | yes | yes |
Form state management | “state” | “state” | redux |
Field state management | “state” | “state” | redux |
has basic component | yes | false | false |
Array | getFieldDecorator (`names[${k}]`, {…})() | 同 redux-form | <Field name={`${member}.firstName`} /> |
value deliver from values | N/A | Pub/Sub | mapStateProps |
get values | this.props.form. getFieldsValue((value) => {}) | onSubmit(values) | onSubmit(values) |
Performance | reconciler other field | reconciler other field | reconciler other field but scu |
Field | getFieldDecorator (name, {}) | <Field /> | <Field /> |
写法
由于要给 Form 赋上很多功能,antd form 和 redux-form 采用的是 HOC,HOC 看起不太直观,并且多一个步骤。相对于通过 Context 方式少了一点优雅。
redux-form 在使用了 HOC 的同时还使用了 Context,混合的使用方式,吸取了 HOC 的 proxy props 的长处为 Field 赋上 onChange 等事件。
antd from 借助 API getFieldDecorator() 来实现表单元素的“双向绑定”略显繁琐。
性能
一下结论都是基于 debug 得出的。
antd from 行为类似于 react-final-form
react-final-form。一个表单元素的改动会触发同一个 form 内的其他表单元素更新,浪费性能
redux-form 由于是通过表单元素自己来管理 state 只有在失去焦点的时候才触发整个 form 表单的更新
实现重用
form 元素有大量需要重用的逻辑
1,数据更新,状态管理,“双向绑定”
2,数据校验,正则,异步,限制输入,错误提示
3,onChange 事件
4,format
那么三大 form 组件库是怎样实现重用的呢?
基本思路是在展现元素外层包一层组件,所有逻辑都在外层组件实现。
react 实现重用的方式有 HOC,render props 和 mixin。 当然 mixin 已经不推荐了。
以上方法都是解决横切关注点的问题。下面介绍下HOC,render props 由于 mixin 官方已经不推荐了,有兴趣的同学可以看看 Mixins Considered Harmful
HOC
|
|
HOC 能带来
1,相同的生命周期函数。处理例如挂载监听与卸载时卸载监听。
2,props 相同的处理逻辑,这正是表单元素需要的。
在使用 HOC 不建议改变原始组件,所以输入提示就不适合用这种方式来做。
render props
|
|
可以看到 render props 支持三种渲染方式,但是目的都只有一个处理 props。render props 能带来
1,与 HOC 一样, props 相同的处理逻辑
2,动态 children
以上两种方式虽然分开介绍,但是它们时可以组合使用的。
自定义表单元素
antd from: getFieldDecorator()(CustomizeComponent)
CustomizeComponent 里面需要调用 this.props.onChange(value)
react-final-form:
children
(props) => {};render
(props) => {};component
creactElement(component);
需要调用 props.input.onChange(value)
redux-form: creactElement(component);
也需要调用 props.input.onChange(value)
function as children 每次父组件有更新,都会导致子元素的重新创建。导致性能浪费。但是这样满足强的单向数据流,不用关心组件状态更新的问题,cwrp 这个坑也就成功避免了。
这里发现没有一个 form 框架使用正常的 props.children 做为子组件,为什么呢?
参考 http://slides.com/jiannian/deck-1