业务需求: 用两个单独的el-date-picker 实现开始时间和结束时间;
开发操作: 直接copyElementUi日期组件放置在代码中;
出现问题:开始时间选择可以小于结束时间;
解决方法一(简单方法):
- .html (在原来的结构上加入picker-options属性)
<el-date-picker
class="date"
v-model="range[0]
:picker-options="startDatePicker"
type="date"
value-format="yyyy-MM-dd" // 日期格式,可以跟着自己的需求改变
placeholder="开始时间">
</el-date-picker>
<el-date-picker
class="date"
v-model="range[1]"
:picker-options="endDatePicker"
type="date"
value-format="yyyy-MM-dd" // 日期格式,可以跟着自己的需求改变
placeholder="结束时间">
</el-date-picker>
- .js
data() {
return {
range: [],
startDatePicker: this.beginDate(),
endDatePicker: this.processDate(),
};
},
methods: {
beginDate(){
const self = this;
return {
disabledDate(time){
let endTime = self.range[1];
if (endTime) { // 如果结束时间不为空,则小于结束时间
endTime = endTime.replace(/-/g, '/'); // 正则匹配转换,例如‘2020-01-01’ 转成 ‘2020/01/01’
return time.getTime() > new Date(endTime).getTime();
}
}
}
},
processDate() {
const self = this;
return {
disabledDate(time) {
let startTime = self.range[0];
if (startTime) { // 如果开始时间不为空,则结束时间大于开始开始时间
startTime = startTime.replace(/-/g, '/'); // 正则匹配转换,例如‘2020-01-01’ 转成 ‘2020/01/01’
return time.getTime() < new Date(startTime).getTime();
}
}
}
}
},
watch: {
range(val) {
let endTime = val[1];
if (endTime) {
endTime = endTime.replace(/-/g, '/');
val[1] = new Date(new Date(endTime).getTime() + (3600 * 1000 * 24 - 1));
// 手动将日期设置endTime为当天的23:59:59
}
}
}
解决方法二(封住成vue组件,升级版):
父组件
<date-range-picker
@change="filterSearch"
v-model="item.value"></date-range-picker>
子组件
<template>
<div class="date-range-picker">
<input :value="value" class="hidden"/>
<div class="start">
<el-date-picker
v-model="range[0]"
type="date"
:clearable="true"
:picker-options="startPickerOption"
placeholder="开始日期">
</el-date-picker>
</div>
<div class="end">
<el-date-picker
v-model="range[1]"
type="date"
:clearable="true"
:picker-options="endPickerOption"
placeholder="结束日期">
</el-date-picker>
</div>
</div>
</template>
<script>
export default {
name: 'date-range-picker',
props: {
value: {
type: Array,
default() {
return [];
},
},
},
data() {
return {
range: this.value || [],
$_range: [], // 这个相当于是上次记录,记录上次的值
isChange: false, // 感觉这个只走了一次
startPickerOption: {
disabledDate: (time) => {
if (!this.range) {
return false;
}
if (!this.range[1]) {
return false;
}
return time.getTime() > this.range[1].getTime();
},
},
endPickerOption: {
disabledDate: (time) => {
if (!this.range) {
return false;
}
if (!this.range[0]) {
return false;
}
return time.getTime() < this.range[0].getTime();
},
},
};
},
watch: {
value(val1) {
let val2 = this.$_range || [];
this.$_range = [].concat(val1 || []); // 将当前信息赋值给_range,留待下次变化对比使用
let times = (val1 || []).map((v) => { // 本次记录的时间戳集合
if (v) {
return v.getTime();
}
});
val2 = val2.map((v) => { // 上次记录的时间戳集合
if (v) {
return v.getTime();
}
});
if (val2 && val2.length) { //不是第一次使用组件
times.forEach((v, index) => {
if (v && v !== val2[index]) { // 判断是否跟上次操作的数据一致 ,v是为0点的endTime(v为用户手动操作得到的
if (index) { // 下标为1 的时候,val2[index] 一定是处理为23:59:59后得值)
let endTime = times[index] + (3600*1000*24-1); //处理endTime
if (endTime !== val2[index]) { // 处理后进行对比
val1[index] = new Date(endTime); // 不一样,说明用户进行了修改,重新赋值
this.isChange = true; // 引发变化
}
} else {
this.isChange = true; // 引发变化
}
}
});
} else { // 第一次使用组件
if (times[1] && (String(new Date(times[1])).indexOf('00:00:00') > -1)) {
// 判断第一次使用组件时endTime是否有值并且父级传来的值是否需要转换
val1[1] = new Date(times[1] + (3600*1000*24-1)); // 将endTime设置为当天的23:59:59
}
}
this.range = val1 || []; // 处理好的数据返回给this.range
},
range(val1) {
this.$emit('input', val1); // 触发emit
if (this.isChange) {
this.isChange = false;
this.$emit('change', val1); // 变化后,触发emitchange
}
},
},
};
</script>
<style lang="scss">
.date-range-picker {
position: relative;
border: 1px solid #ddd;
border-radius: 3px;
overflow: hidden;
height: 32px;
input {
border: none;
height: 100%;
}
.hidden {
display: none;
}
.start, .end {
position: absolute;
top: 0;
width: 50%;
height: 100%;
.el-date-editor.el-input {
width: 100%;
height: 100%;
}
}
.start {
left: 0;
}
.end {
right: 0;
}
.el-input__inner{
border: none;
}
}
</style>
接下来,简单描述下遇到的问题,
相信大家也看到了, 我在上面使用正则转换了一下时间格式, 这是为什么呐?
是因为我el-date-picker设置的时间格式为yyyy-MM-dd, 所以我拿到的就是2020-01-01;
我们试下new Date() 会出现什么
咦,惊奇的发现为什么时间是当天的8点,而不是0点呐?
快,百度一下,你就知道!!!
哈哈,答案来喽
-
解决方法一
简单的方法的话直接拼接成'2020-01-01 00:00:00';
展示结果:
-
解决方法二
使用下刚刚的正则试下
哎,居然好使了耶,
解释下原因(借鉴下面参考文章中的说法):
我们所在的时区是东八区,如果以GMT标准0点来算的话,在那个时间点,这里就是8点啊。
那我就可以这样理解了,创建时间时,它默认时间确实是0点,但是是以GMT为基准的,所以将其转换成本
地时间就是8点。而/分割的字符串在创建时,则是以本地时区为基准。
那么为什么js会对不同分割的时间字符串进行不同处理呢?貌似是因为-分隔且具有前导0的日期字符串,会
被解析成ISO格式的字符串,以GMT时区为基准,不过该答主也没看懂 结尾
结合实践操作,以上问题已经得到了解决,哈哈, 快去实验下吧,
觉得解决了问题, 请点赞哦参考文章
js new Date 创建时间默认是8点
elementUI 日期时间选择器el-date-picker开始时间与结束时间约束