子组件
<template>
<div>
<el-date-picker
v-model="dateModel"
type="datetimerange"
:picker-options="pickerOptions"
range-separator="至"
ref="picker"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="defaultTime"
/>
</div>
</template>
<script>
// 定义一天的毫秒数
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
export default {
props: {
// 日期范围值
value: {
type: Array,
default: () => []
},
// 选择的日期范围限制
limit: {
type: Number,
default: Infinity
},
// 是否禁止选择当前日期之后的日期
disableCurrentDateLater:{
type:Boolean,
default: false
},
// 只能选择当前日期之前的天数限制
daysLimit: {
type: Number,
default: Infinity
},
// 是否显示快捷选项
showShortcuts:{
type:Boolean,
default: true
},
// 默认开始和结束时间的时分秒
defaultTime:{
type: Array,
default: () => (['00:00:00', '23:59:59'])
}
},
data() {
return {
// 日期选择器的选项
pickerOptions: {
onPick: this.handlePick,
disabledDate: this.isDisabledDate,
shortcuts: this.showShortcuts ? this.getShortcuts() : [],
},
};
},
methods: {
// 处理日期选择
// 当选择的最小日期存在时,如果已经存在pickerMinDate,则将其置空;如果不存在pickerMinDate,则将选择的最小日期赋值给pickerMinDate
handlePick({ minDate }) {
const now = new Date();
now.setSeconds(0, 0); // 清除秒和毫秒
if (minDate && this.pickerMinDate) {
this.pickerMinDate = null;
} else if (minDate) {
this.pickerMinDate = minDate.getTime();
}
},
// 判断日期是否被禁用
// 如果pickerMinDate存在,则判断日期是否超出范围或者在当前日期之后;如果pickerMinDate不存在,则判断日期是否在30天前或者在当前日期之后
isDisabledDate(time) {
const now = new Date();
const thirtyDaysAgo = now.getTime() - this.daysLimit * ONE_DAY_MS;
if (this.pickerMinDate) {
return this.isDateOutOfRange(time, thirtyDaysAgo, this.pickerMinDate) || this.isDateAfterNow(time, now);
}
return time.getTime() < thirtyDaysAgo || this.isDateAfterNow(time, now);
},
// 判断日期是否超出范围
// 如果日期在pickerMinDate的limit天之后,或者在pickerMinDate的limit天之前,或者在30天前,则返回true,表示日期超出范围
isDateOutOfRange(time, thirtyDaysAgo, pickerMinDate) {
const limitTime = this.limit * ONE_DAY_MS;
return (time.getTime() > (pickerMinDate + limitTime)) || (time.getTime() < (pickerMinDate - limitTime)) || time.getTime() < thirtyDaysAgo;
},
// 判断日期是否在当前日期之后
isDateAfterNow(time, now) {
return this.disableCurrentDateLater && time.getTime() > now.getTime();
},
// 获取快捷选项
getShortcuts() {
return [{
text: '最近一周',
onClick: this.getShortcutPicker(7)
}, {
text: '最近一个月',
onClick: this.getShortcutPicker(30)
}, {
text: '最近三个月',
onClick: this.getShortcutPicker(90)
}];
},
// 获取快捷选项的日期范围
getShortcutPicker(days) {
return (picker) => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - days * ONE_DAY_MS);
picker.$emit('pick', [start, end]);
};
},
},
computed: {
// 日期模型,用于v-model双向绑定
dateModel: {
get() {
return this.value ? this.value.map(date => new Date(date)) : [];
},
set(val) {
if (val) {
this.$emit('input', val.map(date => date.getTime()));
} else {
this.$emit('input', null);
}
}
}
},
};
</script>
父组件
<template>
<div id="app">
<!--
disableCurrentDateLater 当前时间之后的日期是否禁止选择
limit 选择的范围: 比如: 只能选1月1日前后的30天 ,这里就传30
daysLimit 只能选择当前时间之前的多少天
-->
<myDatePicker
v-model="date"
:limit="10"
:daysLimit="30"
disableCurrentDateLater
/>
</div>
</template>
<script>
import myDatePicker from './components/myDatePicker'
export default {
name: 'App',
components: {
myDatePicker,
},
data() {
return {
date: [],
}
},
}
</script>