之前在紧急参与一个PC管理后台的项目,项目的基础架子是花裤衩大佬的vue-element-admin()vue2版本),。其中有一个需求是列表数据中数据回显时候,有关时间部分的数据在回显/编辑的情况下,提交时获取的值有问题。虽然后面解决了,但还是觉得简单粗暴,所以记录下看大佬们有没有更好的方案。
同时也因为自己以为工作关系在学习React,所以选择了ant design vue来跟element-ui做对比,(ant design 有vue和react版本,本次对比选择react版本)
element-ui
数据回显为两个时间,开始时间和结束时间。由于是两个时间在一行,最开始使用的是时间范围选择(is-range),后来发现有问题,先改成分离版本的,交付初版代码。
el-time-picker range版本
最开始使用就是添加is-range属性的版本。参照官方示例
<el-time-picker
is-range
v-model="dataTime"
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
placeholder="选择时间范围"
>
</el-time-picker>
// 日期回显处理
this.dataTime = [new Date('2023/01/01 ' + row.beginTime), new Date('2023/01/01 ' + row.endTime)]
// 获取dataTime的值
[
Sun Jan 01 2023 05:00:00 GMT+0800 (中国标准时间),
Sun Jan 01 2023 08:00:00 GMT+0800 (中国标准时间)
]
- 经过日期转换之后,回显正常,但获取到的值是标准日期格式
<el-time-picker
is-range
v-model="dataTime"
range-separator="至"
:picker-options="pickerOption"
value-format="HH:mm:ss"
start-placeholder="开始时间"
end-placeholder="结束时间"
placeholder="选择时间范围"
>
</el-time-picker>
- 添加format格式化之后,回显后不修改获取的值仍是标准日期格式;修改任一个时间就是时分秒的格式。
以上的倒还好说,自己做下转化处理应该也能解决。但是在新增时候有一点是最不符合需求的:开始-结束的时间有多个,有的时必填项,有的时非必填项。
而is-range版本不符合需求的原因就是必须要默认值。。。(新增情况下怎么可能会给非必填项赋默认值,抓狂!!!)
所以在之后就改成时间分离的版本,使用两个时间选择器。
el-time-picker分离版
参照官方例子,默认值要讲述进行日期转化处理。(写文章时才发现问题,后续再讲,是真的坑。。。)
初始版本
- 新增数据
<el-time-picker v-model="beginTime" />
<span>至</span>
<el-time-picker v-model="endTime"/>
// 不选择时间
// { beginTime:undefined,endTime:undefined }
// 选择时间
// { beginTime:Sun Jan 01 2023 17:11:20 GMT+0800 (中国标准时间),
// endTime:Sun Jan 01 2023 17:12:22 GMT+0800 (中国标准时间)
// }
这样的话,不选时间时得到的值是undefined,选择时间后的值是标准时间格式,
- 编辑数据
// 数据处理
this.beginTime = new Date('2023/01/01 ' + row.beginTime)
this.endTime = new Date('2023/01/01 ' + row.endTime)
// 不修改/修改时间
// { beginTime:Sun Jan 01 2023 17:11:20 GMT+0800 (中国标准时间),
// endTime:Sun Jan 01 2023 17:12:22 GMT+0800 (中国标准时间)
// }
而需求上要求的是时-分-秒格式。所以针对显示问题,加了format和value-format。
format版本
- format是在pickerOption中,是页面中选中时间的显示格式
- value-format是获取值的显示格式
<el-time-picker
v-model="beginTime"
:picker-options="pickerOption"
value-format="HH:mm:ss"
/>
<span>至</span>
<el-time-picker
v-model="endTime"
:picker-options="pickerOption"
value-format="HH:mm:ss"/>
// js部分
pickerOption: {
format: 'HH:mm:ss'
}
二者的区别在于格式显示的选择不同,
TimePicker中format的选择格式为:小时:
HH
,分:mm
,秒:ss
,AM/PMA
而value-format的选择格式则为日期格式,时分秒的部分是相同的,也有另外一部分,(12小时制和24小时制)主要区别在于:大写是24小时,小写为12小时;单字母为不补0格式,双字母补0;大写A代表AM/PM,小写a代表am/pm 。
加完之后,不选择时候为空字符串,选完为HH:mm:ss格式。但还有问题。
问题在于: 详情数据回显时候,是以new Date() 格式填充,如果不做修改,获取的值就会是标准时间格式,而不是value-format规定的格式,所以就是个坑,具体情况如下:
// 回显后不做修改(Date格式)
beginTime Sun Jan 01 2023 17:11:20 GMT+0800 (中国标准时间),
endTime Sun Jan 01 2023 17:15:20 GMT+0800 (中国标准时间),
// 回显后修改(String格式)
firstBeginTime 17:11:20
firstEndTime 17:15:20
所以,我这里就做了一下处理:如果获取得值不为字符串,则进行日期格式的处理。还单独封装了个函数,经过函数处理后,再转化为时分秒格式。
transTimeFormat (time) {
if (typeof time === 'string') {
const date = parseTime(new Date(), '{y}/{m}/{d}')
time = date + ' ' + time
}
return time
},
这里算是勉强可以使用,功能正常,新增和编辑情况下获取的值都是时分秒格式的字符串。这也是我交上去的代码初版。
最新版
但是,在我写这篇文章的时候才发现一个细节:分离版的时间选择器绑定的值可以是字符串!!!
这个细节也是我无意间测试出来的。
在分离版的第一份代码里,还没有处理回显时的日期转化时,值的结果情况与之前一样。
<el-time-picker v-model="beginTime" />
<span>至</span>
<el-time-picker v-model="endTime"/>
比较偶然的是,加了format之后,我依旧没有处理回显时的日期转化,但此刻的情况变了
<el-time-picker
v-model="beginTime"
:picker-options="pickerOption"
value-format="HH:mm:ss"
style="width:180px"
/>
<span>至</span>
<el-time-picker
v-model="endTime"
:picker-options="pickerOption"
value-format="HH:mm:ss"
style="width:180px"
/>
- 新增情况:未选择时为空字符串,选择后为时分秒格式
- 回显情况:回显正常,修改与否都为时分秒格式
天!!!这就是我希望的情况,是什么原因呢?所以我就发现了v-model绑定的格式问题
怪我,怪我学艺不精,囫囵吞枣。。。
antd design react
这一份的内容,主要作用是进行下对比。在学习React相关东西,就拉过来做个比较,我觉得这种问题肯定每个框架都会遇到,但各自的处理应该会不一样。
代码比较简略,莫介意哈
TimePicker
react中引入了moment插件,在给时间选择器回显的时候,先经过moment处理,不然会报错。
这样就导致了就是未修改的情况和修改的情况下获取到的值都是moment对象,在提交时候需要进行一次moment处理。(诶!这好像和我处理的方式有点像啊😎,略同,略同,哈哈哈)
Form.setFieldsValue({
time: moment(time, 'HH:mm:ss')
})
<Form
form={addOrEditForm}
labelCol={{ span: 4 }}
wrapperCol={{ span: 16 }}
>
<Form.Item
label="时间"
name="time"
rules={[{ required: true, message: '请选择时间' }]}
>
<TimePicker size="large" format='HH:mm' />
</Form.Item>
</Form>
Form
.validateFields()
.then((values) => {
let time = moment(values.time).format('HH:mm:ss')
console.log(time);
})
其他的就不在多对比了,主要内容还是最新版的正确。话说有没有和我一样遭遇的同学,欢迎评论区畅谈心路历程(本人OS: 坑,大坑,一大坑,是一大坑,就是一大坑)