最近在折騰
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哈哈~