react->Ant Design->日期控件DatePicker数据提交格式设置

最近在折腾react,因此,将一些本身碰到的问题以及对应的解决办法分享出来,期待和你们共同探讨和进步!react

概述

react折腾系列之二:如何在ant框架下,form表单中,灵活设置DatePicker提交服务器的数据格式。ios

例如:日期展现为:“2018-08-08”,而后提交服务器的时候,提交为:1533657600000(即:new Date('2018-8-8').getTime()的值)。ajax

经过官方文档,咱们知道,能够经过format字段设置日期格式,而且其值是一个moment对象。因此你可能会想到:json

  • 设置format为"YYYY-MM-DD"
  • 在提交服务器前,经过该日期选择框的moment对象获取到对应的long型数值,而后提交

固然也是ok的,可是这样会比较麻烦,毕竟每一个相关的ajax请求,都须要加上这样的逻辑。axios

本着,拒绝重复工做和本身的事情本身作的原则,咱们但愿组件自身支持这样的功能。bash

问题描述清楚了,再提一下,本文以axios为例进行讲解,毕竟不同的库,处理方式可能不同,可是道理是相通的。服务器

步骤一:看文档

理所固然,首先应该把DatePicker的官方文档啃一遍,看看支不支持该功能。antd

固然,我已经啃过,就由于没有,才会有本文。app

读者能够先自行脑补一下,若是是你,会怎么实现这个功能呢。框架

步骤二:理清getFieldDecorator与控件的交互逻辑

在进行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的是怎么获取到控件的值的呢?

图片1

从上图的react devtools中,咱们能够看到,通过getFieldDecorator包装,antDatePicker控件上注入的相关属性,其中包括了几个事件监听方法(灰色框框部分),其中onChange嫌疑最大,先拿它开刀。

先来看看开刀前的效果,上面代码console.log('values--', values)打印结果以下:

图片2

发起请求后,数据以下:

图片3

步骤三:验证getFieldDecorator与onChange的关系

接下来,咱们验证一下,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"。结果以下图:

图片3
图片4

上面的图片说明咱们的猜想是正确的,可是这只是成功了一半,咱们还须要让moment对象传给axios后,在提交的时候自动把本身转成long型。

步骤四:理清moment经axios后是如何转换的

从上面的请求截图能够看出,moment对象最终会被转换成UTC时间格式的数据。并且咱们也能够很清晰的猜出,这个过程是在axios中进行的。

关键是怎么转的,由于这是两个彻底解耦的第三方库,因此不多是经过调用moment特有的方法实现的,应该是Object上的通用方法。具体是什么呢,toStringvalueOf?仍是其余的呢?

如何验证呢。。。

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哈哈~

相关文章
相关标签/搜索