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

相關文章
相關標籤/搜索