最近在折腾
react
,因此,将一些本身碰到的问题以及对应的解决办法分享出来,期待和你们共同探讨和进步!react
react
折腾系列之二:如何在ant
框架下,form表单中,灵活设置DatePicker
提交服务器的数据格式。ios
例如:日期展现为:“2018-08-08”,而后提交服务器的时候,提交为:1533657600000(即:new Date('2018-8-8').getTime()
的值)。ajax
经过官方文档,咱们知道,能够经过format字段设置日期格式,而且其值是一个moment
对象。因此你可能会想到:json
moment
对象获取到对应的long
型数值,而后提交固然也是ok的,可是这样会比较麻烦,毕竟每一个相关的ajax
请求,都须要加上这样的逻辑。axios
本着,拒绝重复工做和本身的事情本身作的原则,咱们但愿组件自身支持这样的功能。bash
问题描述清楚了,再提一下,本文以axios
为例进行讲解,毕竟不同的库,处理方式可能不同,可是道理是相通的。服务器
理所固然,首先应该把DatePicker
的官方文档啃一遍,看看支不支持该功能。antd
固然,我已经啃过,就由于没有,才会有本文。app
读者能够先自行脑补一下,若是是你,会怎么实现这个功能呢。框架
在进行form
表单开发时,咱们通常会使用ant
官方提供的getFieldDecorator
对控件进行包装后再使用,例如:
<Form>
<Form.Item label="DatePicker">
{getFieldDecorator('date-picker', config)(<DatePicker />)}
</Form.Item>
</Form>
复制代码
而后调用validateFields进行校验,并在其回调中进行数据提交,例如:
props.form.validateFields((err, values) => {
console.log('values--', values)
if (!err) {
// do something
submitForm(values) // 数据提交
}
})
复制代码
若是,你在上面代码中的do something
处,把对应的日期moment
对象转换成long
型,而后再传给submitForm,这样也是能够解决问题的,可是这样就须要在每一个相似的地方书写这样的逻辑,并非咱们想要的。
那么form.validateFields
的是怎么获取到控件的值的呢?
从上图的react devtools
中,咱们能够看到,通过getFieldDecorator包装,ant
往DatePicker
控件上注入的相关属性,其中包括了几个事件监听方法(灰色框框部分),其中onChange嫌疑最大,先拿它开刀。
先来看看开刀前的效果,上面代码console.log('values--', values)
打印结果以下:
发起请求后,数据以下:
接下来,咱们验证一下,getFieldDecorator是否是经过onChange来实现控件值的获取的。
import React from 'react'
import { DatePicker } from 'antd'
import moment from 'moment'
const { RangePicker } = DatePicker
function MyDatePicker (props) {
var oldChange = props.onChange
var newProps = {
...props,
onChange: function (date, dateStrings) {
date[0] = moment("2018-08-08")
date[1] = moment("2019-09-09")
oldChange(date, dateStrings)
}
}
return <RangePicker {...newProps}/>
}
export default MyDatePicker
复制代码
如上面的代码所示,若是咱们的猜想是对的,那么不管你选择的时间区间是何时,打印的结果应该都是"2018-08-08"到"2019-09-09"。结果以下图:
上面的图片说明咱们的猜想是正确的,可是这只是成功了一半,咱们还须要让moment
对象传给axios
后,在提交的时候自动把本身转成long
型。
从上面的请求截图能够看出,moment
对象最终会被转换成UTC时间格式的数据。并且咱们也能够很清晰的猜出,这个过程是在axios
中进行的。
关键是怎么转的,由于这是两个彻底解耦的第三方库,因此不多是经过调用moment
特有的方法实现的,应该是Object
上的通用方法。具体是什么呢,toString
?valueOf
?仍是其余的呢?
如何验证呢。。。
date[0] = moment("2018-08-08")
date[0].toString = function () {
return '123'
}
复制代码
若是发起请求的时候,数据变成了"123",那就说明猜想正确了。
固然,笔者已经帮大家试过了,不是toString
,也不是valueOf
。若是你猜中了,那么恭喜恭喜;若是你没猜中,并且再也想不出来还有哪些方法存在可能性。那咋办。
要么,瞄一瞄服务端开发同窗鄙视的眼神(这种小问题都搞不定?),而后你就有动力继续猜了,O(∩_∩)O哈哈~
要么就只能放大招了,看看axios
的源码了。
// defaults.js中
transformRequest: [function transformRequest(data, headers) {
// 此处省略n行代码
if (utils.isArrayBufferView(data)) {
return data.buffer;
}
if (utils.isURLSearchParams(data)) {
setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
return data.toString();
}
if (utils.isObject(data)) {
setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
return JSON.stringify(data);
}
return data;
}],
复制代码
看出来了吧,原来是经过JSON.stringify(data)
,那么,接下来就好办了。
还不知道怎么办?
看看我鄙视的小眼神,→_→
重写toJSON就好了,(~ ̄▽ ̄)~
import React from 'react'
import { DatePicker } from 'antd'
const { RangePicker } = DatePicker;
function MyDatePicker (props) {
var serverFormat = props.serverFormat
var oldChange = props.onChange
var newProps = {
...props,
onChange: function (date, dateStrings) {
transformMoment(date[0], serverFormat)
transformMoment(date[0], serverFormat)
oldChange(date, dateStrings)
}
}
return <RangePicker {...newProps}/>
}
function transformMoment (myMoment, serverFormat) {
myMoment.toJSON = function () {
serverFormat = serverFormat || 'x'
var value = myMoment.format(serverFormat)
if (serverFormat === 'x') {
value = parseInt(value)
}
return value
}
return myMoment
}
export default MyDatePicker
复制代码
这样,就解决了!结果就不截图了,相信讲到这一步,你本身就能搞定了。并且还能够经过serverFormat
属性,修改提交给服务端的数据格式。
之后你使用起来,就是:
// 提交格式为long型
<Form>
<Form.Item label="DatePicker">
{getFieldDecorator('date-picker', config)(<MyDatePicker />)}
</Form.Item>
</Form>
// 提交格式为"YYYY-MM-DD",例如:2018-08-08
<Form>
<Form.Item label="DatePicker">
{getFieldDecorator('date-picker', config)(<MyDatePicker serverFormat="YYYY-MM-DD" />)}
</Form.Item>
</Form>
复制代码
是否是棒棒的,那么请不要吝啬你的赞。好人一辈子平安,O(∩_∩)O哈哈~